且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

流水线上的思考——异步程序开发模型(2)

更新时间:2022-09-30 20:28:37

上一期我们讲了一个简单的流水线处理流程,正如我们在上期最后所说那样,这个简单的流水线处理流程对于后续有慢设备操作的业务来说,性能有可能偏低。今天我们来讨论一下如何提高性能的方法。
 
首先让我们来大致区分一下一般业务的处理方式。目前我遇到的业务处理有两种方式:
1:业务之间无关联关系。
这种方式的特点在于业务之间不具备前后关系和关联关系。两个业务,哪一个业务放在前面处理,都不会影响到后续处理的结果。例如日志服务器等等。
 
2:业务之间有关联关系。
这种方式的特点就在于业务之间具有一定的关联性,业务处理的顺序不能打乱,必须执行完1以后再执行2。要不然处理的结果将完全出错,或者直接处理出错等等。例如和金钱相关的一些业务。
这两种处理方式,我们需要分开讨论。
今天我们先来讨论第一种方式(业务之间无关联关系)。我们可以先设计一个业务场景,然后针对这个场景来说明我们的处理方式。
业务场景:
我们设计一个日志服务器,这个日志服务器用来接收其它服务器发送来的日志信息,并将日志信息写入到日志数据库中。对于这个日志服务器来说,哪个服务器的日志先写入或者后写入,没有什么必须的要求。
 
根据上一篇原理,我们可以设计出类似下图的流水线处理方式:
流水线上的思考——异步程序开发模型(2)
通过上图,我们就已经做出了一个日志服务器的大致骨架。但是当您运行这个程序的时候,你会发现当大量日志信息发送给日志服务器的时候,CPU的利用率依然不高。那么如何提高CPU的利用率的? ——线程池!您想到的一定和我想到的是一样的。线程池对于这种类型的业务来说的确是个不错的选择。如果您不知道什么叫做线程池的话……好吧,看来你要去先补一补课了,去看看我之前写的一篇文章《IOCP线程池的开发》。如果您已经了解了线程池,那么上面的流水线处理方式将变成这样的。
流水线上的思考——异步程序开发模型(2)
通过这样的改进,我们在原来的单线程日志服务器的基础之上,修改成了一个多线程的日志服务器。经过测试,这种方式对于日志服务器来说性能提升不是一星半点的概念。
好了,我们回过头来看看我们今天设计的这种并行流水线处理方式。
 
我们先站在业务的角度来看业务处理流程:
1IOCP上接收到一个客户端的业务请求,
2:业务被放入业务请求队列。
3:业务请求队列和业务处理队列进行置换。
4:业务处理队列将相应的请求通过IOCP发送给业务处理线程池进行处理。
 
如果我们站在线程的角度来看业务处理流程:
1IOCP中的一个线程将业务写入业务分发线程中的业务请求队列。
2:业务分发线程将业务请求队列和业务处理队列置换。
3:业务分发线程将业务分发给IOCP线程池进行业务处理。
 
通过以上的描述,我们发现,既然我们最后都要将业务请求分发给IOCP线程池,那么我们为什么要先将业务发送给业务分发线程,然后再由这个分发线程分发给线程池呢?这样做不是脱了裤子放屁么?这个业务分发线程是否可以取消掉呢?
 
我觉得,这个问题可以看这个分发线程的处理业务:如果分发线程的作用只是简单的将业务分发给线程池,而没有其它业务的话,那么这个分发线程是完全可以取消的;但如果这个分发线程除了处理分发以外,还要对于一些外围业务进行相应处理的话,我还是建议保留这个分发线程。
例如我曾经做过的一个项目,这个分发线程的作用是有两个功能:
1:将相关业务分发给线程池进行处理。
2:对于一些上线、下线、心跳的外围业务进行简单处理。
对于这样的项目来说,如果有个分发线程的话,处理起来会相对地方便很多。
 
好,我们来总结一下今天讨论的结果。这个结果应该是分两个。
1:对于使用分发线程的情况:
流水线上的思考——异步程序开发模型(2)
2:对于不使用分发线程的情况:
流水线上的思考——异步程序开发模型(2)
在业务线程池中中的业务分发处理部分,如果业务类型比较多时,建议大家可以采用业务编号和处理函数映射的方法。如果业务类型较少时,可以直接使用switch  case来做。
好了,今天的讨论就是这些了,下次我们将讨论业务之间有关联关系的处理方法。今天讨论的东西只是我的一些看法,如果有好的方法,希望大家能直接回复或者在QQ上告诉我,我的QQ是:513479626
本文转自狗窝博客51CTO博客,原文链接http://blog.51cto.com/fxh7622/1142138如需转载请自行联系原作者

fxh7622