上一期我們講了一個簡單的流水線處理流程,正如我們在上期最后所說那樣,這個簡單的流水線處理流程對于后續有慢設備操作的業務來說,性能有可能偏低。今天我們來討論一下如何提高性能的方法。
首先讓我們來大致區分一下一般業務的處理方式。目前我遇到的業務處理有兩種方式:
1:業務之間無關聯關系。
這種方式的特點在于業務之間不具備前后關系和關聯關系。兩個業務,哪一個業務放在前面處理,都不會影響到后續處理的結果。例如日志服務器等等。
2:業務之間有關聯關系。
這種方式的特點就在于業務之間具有一定的關聯性,業務處理的順序不能打亂,必須執行完1以后再執行2。要不然處理的結果將完全出錯,或者直接處理出錯等等。例如和金錢相關的一些業務。
這兩種處理方式,我們需要分開討論。
今天我們先來討論第一種方式(業務之間無關聯關系)。我們可以先設計一個業務場景,然后針對這個場景來說明我們的處理方式。
業務場景:
我們設計一個日志服務器,這個日志服務器用來接收其它服務器發送來的日志信息,并將日志信息寫入到日志數據庫中。對于這個日志服務器來說,哪個服務器的日志先寫入或者后寫入,沒有什么必須的要求。
根據上一篇原理,我們可以設計出類似下圖的流水線處理方式:

通過上圖,我們就已經做出了一個日志服務器的大致骨架。但是當您運行這個程序的時候,你會發現當大量日志信息發送給日志服務器的時候,CPU的利用率依然不高。那么如何提高CPU的利用率的??——線程池!您想到的一定和我想到的是一樣的。線程池對于這種類型的業務來說的確是個不錯的選擇。如果您不知道什么叫做線程池的話……好吧,看來你要去先補一補課了,去看看我之前寫的一篇文章《IOCP線程池的開發》。如果您已經了解了線程池,那么上面的流水線處理方式將變成這樣的。

通過這樣的改進,我們在原來的單線程日志服務器的基礎之上,修改成了一個多線程的日志服務器。經過測試,這種方式對于日志服務器來說性能提升不是一星半點的概念。
好了,我們回過頭來看看我們今天設計的這種并行流水線處理方式。
我們先站在業務的角度來看業務處理流程:
1:IOCP上接收到一個客戶端的業務請求,
2:業務被放入業務請求隊列。
3:業務請求隊列和業務處理隊列進行置換。
4:業務處理隊列將相應的請求通過IOCP發送給業務處理線程池進行處理。
如果我們站在線程的角度來看業務處理流程:
1:IOCP中的一個線程將業務寫入業務分發線程中的業務請求隊列。
2:業務分發線程將業務請求隊列和業務處理隊列置換。
3:業務分發線程將業務分發給IOCP線程池進行業務處理。
通過以上的描述,我們發現,既然我們最后都要將業務請求分發給IOCP線程池,那么我們為什么要先將業務發送給業務分發線程,然后再由這個分發線程分發給線程池呢?這樣做不是脫了褲子放屁么?這個業務分發線程是否可以取消掉呢?
我覺得,這個問題可以看這個分發線程的處理業務:如果分發線程的作用只是簡單的將業務分發給線程池,而沒有其它業務的話,那么這個分發線程是完全可以取消的;但如果這個分發線程除了處理分發以外,還要對于一些外圍業務進行相應處理的話,我還是建議保留這個分發線程。
例如我曾經做過的一個項目,這個分發線程的作用是有兩個功能:
1:將相關業務分發給線程池進行處理。
2:對于一些上線、下線、心跳的外圍業務進行簡單處理。
對于這樣的項目來說,如果有個分發線程的話,處理起來會相對地方便很多。
好,我們來總結一下今天討論的結果。這個結果應該是分兩個。
1:對于使用分發線程的情況:

2:對于不使用分發線程的情況:

在業務線程池中中的業務分發處理部分,如果業務類型比較多時,建議大家可以采用業務編號和處理函數映射的方法。如果業務類型較少時,可以直接使用switch??case來做。
好了,今天的討論就是這些了,下次我們將討論業務之間有關聯關系的處理方法。今天討論的東西只是我的一些看法,如果有好的方法,希望大家能直接回復或者在QQ上告訴我,我的QQ是:513479626
本文轉自狗窩博客51CTO博客,原文鏈接http://blog.51cto.com/fxh7622/1142138如需轉載請自行聯系原作者
fxh7622