放翁(文初)的一畝三分地

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            210 隨筆 :: 1 文章 :: 320 評論 :: 0 Trackbacks

          CometPipe數據發送一點改動

          Author:放翁(文初)

           

          場景:

          前提:長連接推送(每個請求會話時間保持較久)。在事件驅動模式下,多線程可能同時完成任務并通過Http長連接下發數據,對于Response需要有一定的并發保護。

           

          第一版

                   增加一個lock,獲得以后才可以使用Response。

                   每個線程的處理流程:get lock à use response àrelease lock。

                   在同一個通道的事件大量并發產生的時候,由于use response比較“重”,使得大量線程生命周期加大(順序的獲取鎖),上下文切換頻繁,系統load較高。

           

          第二版(現在的版本)

                   去掉lock,為每一個請求會話增加一個隊列和后臺線程。

                   每個線程的處理流程:add message to queue。

                   后臺線程block to wait message and deliver

                   第一版的問題不存在了,但在沒有消息下行的時候,大量后臺線程block wait,對于內存來說還是有些浪費。

           

          復雜卻未必有好效果的版本

          從上面來看,需要做的就是防止將發送數據放入競爭事務(也就是一個時期只有一個線程負責對隊列數據的獲取和下發),需要復用線程為多個請求處理下行任務。


                                                                      

          大致解釋一下流程:

          1.  每個線程在放入隊列的時候需要先獲得讀寫鎖的讀鎖,然后將數據放入隊列。具體獲得讀鎖的目的最后談。

          2.  線程判斷是否已經有后臺支持線程來處理消息下發,如果沒有嘗試的去操作needworkerflag的原子布爾對象。

          3.  線程如果成功的將needworkerflag原子布爾對象由true改成了false狀態,那么表示他獲得了取得線程事件的令牌,就向線程池發起執行下發消息的任務。

          4.  線程池收到任務后,分配一個線程循環的去獲取數據并下發,直到隊列瞬時為空。

          5.  獲取寫鎖,重新再檢查隊列是否有數據,如果有下行,然后修改needworkerflagtrue,最后釋放寫鎖。(用讀寫鎖就是為了在后臺線程退出時保證隊列中的被加入的數據完全被執行,而沒有并發導致遺留數據在隊列但沒有任何線程處理的情況,帶來的壞處就是在這個寫鎖臨界區里面會有寫出動作會阻塞外部在那個時候放數據的過程)

           

          設計很復雜,能夠帶來的比第二個設計好的點就是可能在消息并發較低的時候充分利用資源,但壞處還是很多的,包括線程切換,線程退出時的短時阻塞,線程池容量大小的考慮。

           

          大家如果有更好的設計和實現的方式可以一起討論并給出設計和實現的細節說明。

           

          posted on 2011-06-23 12:16 岑文初 閱讀(4554) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 大港区| 高陵县| 湖北省| 将乐县| 普兰店市| 云林县| 牟定县| 库尔勒市| 耒阳市| 色达县| 临夏市| 崇明县| 宁陕县| 合作市| 都匀市| 洛南县| 雷山县| 涪陵区| 涟源市| 衡阳县| 台州市| 宣化县| 安康市| 丽水市| 高雄市| 电白县| 定兴县| 独山县| 商河县| 永平县| 连城县| 重庆市| 安达市| 赤水市| 紫阳县| 顺平县| 大石桥市| 江源县| 双辽市| 余姚市| 宝应县|