架构设计:生产者/消费者模式 第4页:注意事项

2014/05/06 15:27
阅读数 168

顺便补充几个注意事项,大伙儿留意一下:

    1、对stdio进行读写操作是以阻塞方式进行。比如管道中没有数据,消费者进程的读操作就会一直停在哪儿,直到管道中重新有数据。

    2、由于stdio内部带有自己的缓冲区(这缓冲区和管道缓冲区是两码事),有时会导致一些不太爽的现象(比如生产者进程输出了数据,但消费者进程没有立即读到)。具体的细节,大伙儿可以看"这里"。

    ◇SOCKET(TCP方式)

    基于TCP方式的SOCKET通讯是又一个类似于队列的IPC方式。它同样保证了数据的顺序到达;同样有缓冲的机制。而且这玩意儿也是跨平台和跨语言的,和刚才介绍的shell管道符方式类似。

    SOCKET相比shell管道符的方式,有啥优点捏?主要有如下几个优点:

    1、SOCKET方式可以跨机器(便于实现分布式)。这是主要优点。

    2、SOCKET方式便于将来扩展成为多对一或者一对多。这也是主要优点。

    3、SOCKET可以设置阻塞和非阻塞方法,用起来比较灵活。这是次要优点。

    4、SOCKET支持双向通讯,有利于消费者反馈信息。

    当然有利就有弊。相对于上述shell管道的方式,使用SOCKET在编程上会更复杂一些。好在前人已经做了大量的工作,搞出很多SOCKET通讯库和框 架给大伙儿用(比如C++的ACE库、Python的Twisted)。借助于这些第三方的库和框架,SOCKET方式用起来还是比较爽的。由于具体的网 络通讯库该怎么用不是本系列的重点,此处就不细说了。

    虽然TCP在很多方面比UDP可靠,但鉴于跨机器通讯先天的不可预料性(比如网线可能被某傻X给拔错了,网络的忙闲波动可能很大),在程序设计上我们还是 要多留一手。具体该如何做捏?可以在生产者进程和消费者进程内部各自再引入基于线程的"生产者/消费者模式"。这话听着像绕口令,为了便于理解,画张图给 大伙儿瞅一瞅。

    这么做的关键点在于把代码分为两部分:生产线程和消费线程属于和业务逻辑相关的代码(和通讯逻辑无关);发送线程和接收线程属于通讯相关的代码(和业务逻辑无关)。

    这样的好处是很明显的,具体如下:

    1、能够应对暂时性的网络故障。并且在网络故障解除后,能够继续工作。

    2、网络故障的应对处理方式(比如断开后的尝试重连),只影响发送和接收线程,不会影响生产线程和消费线程(业务逻辑部分)。

    3、具体的SOCKET方式(阻塞和非阻塞)只影响发送和接收线程,不影响生产线程和消费线程(业务逻辑部分)。

    4、不依赖TCP自身的发送缓冲区和接收缓冲区。(默认的TCP缓冲区的大小可能无法满足实际要求)

    5、业务逻辑的变化(比如业务需求变更)不影响发送线程和接收线程。

    针对上述的最后一条,再多啰嗦几句。如果整个业务系统中有多个进程是采用上述的模式,那或许可以重构一把:在业务逻辑代码和通讯逻辑代码之间切一刀,把业 务逻辑无关的部分封装成一个通讯中间件(说中间件显得比较牛X :-)。如果大伙儿对这玩意儿有兴趣,以后专门开个帖子聊。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部