<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

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

    Author:放翁(文初)

    Date: 2010/4/14

    Email:fangweng@taobao.com

    緣起

             早在兩年前做開放平臺的時候,由于平臺的特質,就開始尋求對于Web請求異步的解決方案,當時JettyTomcat都在最新的版本中集成類似于CometAsyn Process的功能,但經過測試,效果不佳,因此也沒有再深入去了解其中的一些設計理念。時隔兩年,依然在做開放平臺,但當研究twitterfacebook api的時候,發現已經有了Streaming 模式的Web請求處理模式,由此又再次的去了解今天,在Servlet3規范已經逐漸成熟的情況下,容器,開源項目對于Web請求的異步化是否已經有了很大的提高。在我看來,傳統的Web Container要改造成為異步模式要解決內在和外在兩方面問題,內在需要將那么多年的成熟體系打破,以分階段,異步化的方式來利用現有的功能(異步化很大問題就是復雜了流程,包括對多任務多線程的協調,對資源的分配和回收等等),外在就是要讓用戶如何能夠在最小的代價下移植到異步模式的場景(如果代價很大,那么就很難在已有系統上推廣,同時使用的學習曲線也是推動新技術的一項很重要的指標)。閑話不多說,后續會從概念,到具體的概念實現,最后到實際測試,給一個完整的評估。目標很明確,最基本要學會設計中的一些好的思想,如果能夠找到使用場景就嘗試使用,最終在具體場景下改造現有系統比對效果。

    Comet & Async Request Process

    概念

    CometAsync Request Process的技術已經不算是什么新鮮事物了,但是真正在后臺業務體系中大量使用其實還不多,主要原因還是現在成熟的Web容器都是基于servlet 2.5實現,遵循的也是標準的Http無狀態應答式請求處理模式。但隨著互聯網應用不斷發展,時刻都以人為本的情況下,如何讓用戶體驗不斷提升,就要求能夠在很多場景盡量減少交互延時,盡量多的有人性化的展現(更多的數據交互)。因此,CometAsync Request Process的應用場景就誕生了,這里我只是說應用場景誕生了,也表明其實傳統的應答式請求處理模式在很多場景還是有他的優勢。

             Comet中文如果直譯叫做彗星,其實是比較形象的一種說法。Comet在某些場景下也被叫做Http StreamingComet作為一種技術手段,其實是指在客戶端和服務端建立連接后,可以由服務端主動發起請求將數據推送給客戶端,而客戶端根據推送的數據增量迭代的更新展示。因此服務端的數據推送就好比彗星一樣不定時的傳送到了客戶端。

             Async Request Process也可以被叫做long polling,表示異步請求處理。Async Request Process和傳統的Http請求的差別就和BIONIO差別類似。Web容器或者傳統的Socket應用在處理請求的時候,通常都是One Connection One Thread來處理,申請資源的回收速度根據業務處理來決定,如果后端處理的慢,那么在連接輸入和輸出部分的資源就會閑置而導致浪費(input buffer output buffer),通過Selector和事件模型可以將流程切割成為更細的任務階段,提高資源利用率。

    優缺點及應用場景

    Servlet3規范中已經將CometARP(Async Request Process)都作為基本內容涵蓋在內,很多支持servlet3的容器也都已經支持了這些特性,后面會具體的談到。但是這些特性其實也是在一些特定場景下才會體現出其價值,同時也存在著自身的不足之處。

             Comet與傳統的處理模式最大的特點就在于http通道的長連接和服務端主動推送,基于事件模型。對于客戶端頻繁要去獲取狀態數據或者消息數據的場景下,通過傳統的請求方式來輪詢會極大消耗服務端的資源(帶寬和業務處理能力),同時反復建立數據連接也會造成服務端和客戶端性能的消耗。但另一方面,其實這兩個特點也會成為缺點,保持長連接會導致大量的連接資源消耗(如果沒有數據傳輸的話),另一方面服務端如果數據推送過于頻繁,會導致客戶端崩潰。

             對于Comet和傳統Http請求處理的取舍,需要考慮這些因素:

    1. 是否是單個客戶端反復需要請求服務端獲取數據或者狀態的場景。是則繼續2的判斷,否則考慮使用傳統的方式。

    2. 客戶端數目多少。如果客戶端數目不多,則直接采用Comet,否則考慮第三點。

    3. 單個客戶端對于服務端請求的頻度。(主要是由服務端數據狀態變化的頻度來決定),頻度高,則考慮才用Comet,因為如果頻度高,那么長連接的利用率就會高,則長連接帶來的消耗就可以忽略。

    對于服務端數據推送過多導致客戶端崩潰,可以通過在服務端做數據合并或者在客戶端丟棄數據的方式來提升性能。(建議在服務端處理,減少帶寬和兩方的性能消耗)

    最后就是Comet的編程模型基于事件模式和Http長連接,那么首先需要選擇新版本的容器,例如Tomcat7或者jetty6以上或者glassfish的新版本,其次服務端開發需要符合事件模型驅動的設計,客戶端也需要支持長連接的數據增量推送處理和展示。另一方面確保你的網絡方面在做LB的時候不會由于Http長連接過多導致LB性能大幅度下降,同時客戶端網絡如果質量不好也會間接導致服務端Load上升。

    Async Request Process的特點在于長連接和類似于NIO的設計理念,將服務請求處理過程更加細化,基于事件模型驅動和Selector的方式,提高了高并發下的服務處理能力,同時也在資源管理方面提供了更多的優化空間。ARP在不同的容器中或者開源項目中實現的細節都有可能不同,特別是對于請求的掛起,喚醒,終止,對于資源的分配,回收,都有自己的優化和設計思路,后續再介紹JettyContinuation會談到它的一些設計理念。在一定程度上Comet設計是包含了ARP的,ARP只負責一次請求的交互。ARP的優勢就在于能夠最大限度優化容器或者Socket連接處理能力,優化資源分配,提高并發處理能力。劣勢在于編程習慣不符合常規的模式,對框架的要求高(異步協同,線程和資源管理等,由此帶來的復雜度會導致可用性會受到影響)。

    對于ARP和傳統Http請求處理的取舍,需要考慮這些因素:

    1. 是否是高并發應用。不是則選擇傳統方式,是則考慮第二點。

    2. 服務處理時間較長或者不確定。如果處理時間很短,業務邏輯極為簡單,則選擇傳統方式,否則考慮第三點。

    3. 瓶頸是否在后端,優化前端處理能力是否會產生反效果。如果后端處理能力強,前端是瓶頸,則選擇ARP,如果后端已經到了無可優化的地步,則考慮采用傳統方式。

    今天很多人沒有去使用ARP方式,一方面是容器的不成熟,其次也是因為當前前端不是瓶頸,而且靠堆機器很容易解決問題,而后端例如數據庫,存儲成為了瓶頸,因此前端優化反而會將水流放的更多,導致后端在沒有優化或者無法優化的情況下瓶頸劣勢顯示的更加突出。因此優化系統不是對局部的優化,而是對整個系統自下而上的優化,任何一個關鍵路徑成為瓶頸,那么其他的優化都失去意義。

             這里也實際的舉兩個例子來說明TOP在那些實現中需要用到CometARP

             ARP的兩個應用場景:

    TOP最大的一個難點就是服務的隔離問題,所有的淘寶服務無差別的被集成在TOP的服務集群中,TOP的一個基本功能就是Proxy,由于不同服務的處理能力不同,響應時間也是不同,對于圖片上傳類服務處理速度可能平均要到300ms,而對于普通的請求可能就只需要幾ms,而對于容器連接資源的申請卻都是一樣的,一個Request對應一個Thread去處理,當后端某個服務出現問題或者響應較慢的時候,那么會導致容器的連接資源被大量hold,最后影響到其他服務的正常中轉。這里回顧我剛才談到使用ARP的幾個判斷點,首先需要處理大并發的情況(當前每天3億多次api的服務call,到年底估計會有10億左右的call),其次后端服務處理時間是不定的,有些長有些短,有些根據服務當前所處壓力而不同,最后平臺的服務由于單個問題而影響全部,其實表明后端服務能力其實不是瓶頸(當然對于出現問題的服務會采取降級和保護的措施,在沒有實施保護的時候需要能夠繼續提供對于其他正常服務的中轉)。

    TOP的請求處理流程其實可以分成很多個Pipe,有安全的Pipe,有業務預處理Pipe,有業務轉發Pipe,有業務后處理Pipe等等,其中參數的解析和處理及業務轉發等待回應是最消耗的兩個Pipe,參數解析當前通過lazy讀取stream來減少錯誤請求對于內存的消耗(這同jetty的一個設計類似),對于業務中轉及等待回應的過程其實可以作為一個異步的事件交由服務框架處理,而將請求接收處理線程掛起,釋放掉必要的資源(輸入輸出緩沖),提高整體處理能力。

    Comet的應用場景:

    對于很多大商家需要能夠比較及時的了解當前的交易處理狀況和訂單情況,因此需要有API能夠支持這樣的場景。最初采用類似于notify的方式去實現,但是在實施的過程中發現,外部服務notify的成本過高(服務回調地址的接收能力及可用性較差,服務端的資源大量消耗),最后修改成為客戶端有限制的定期輪詢獲取增量數據。其實,現在外部宣稱很多對外的http方式的notify都不是很靠譜,也有類似于pubsubhubbub的方式,但其實這也增加了一層訂閱關系的中轉和維護的成本。如果采用Comet的方式,一來可以節省大量輪詢帶來的開銷,同時復用長連接可以減少外部連接產生的通信消耗,在加上對數據推送的優化合并,在一定程度上可以實現外部數據推送的場景。

    同樣還有在產品推廣的業務上,當很多外部店鋪推廣一款商品時候,如果商品發生了變化需要能夠告知推廣的應用插件,如果靠輪詢會給TOP帶來不小的壓力,因此通過修改事件觸發Comet事件來更新商品推廣信息。

    外部開源實現

             外部有很多項目實現了CometARP,這里就舉出其中一部分:

             Web容器:

             Jetty 6以上的版本(Continuation),Tomcat 6以上,JBoss配置resteasyglassfishglassfishgrizzly容器內核天然支持)

             開源項目:

             asyncWeb(基于mina)和xsocket

             具體的使用可以參看這些項目的技術文檔,我這里只是給出一些設計的特點說明,在異步模式下的Web請求(實踐篇)中結合詳細改造和測試來說明具體的實施效果及在改造過程中需要注意的內容。

             Jetty

             我個人比較喜歡的一個內嵌式容器,現在像GAEHadoop都在用它,它也是最早支持CometARP的容器。在我過去的基于SCA規范的服務框架中,發布REST的內嵌容器就采用的是Jetty,處理能力還是比較強,在業務協議方面也支持比較廣(同時支持ajp協議,ssl等)。^_^有點打廣告了

             Jetty中的異步處理叫做Continuation,這里不是基于事件驅動模型的,而是通過Continuation這個對象來suspend/resume請求處理線程,同時它的suspend/resume也不是和傳統的wait/notify一樣,在阻塞的地方直接掛起或者被喚醒。它的resume其實又再次模擬了請求,會二次進入服務處理流程,同時第一次和第二次請求數據是不共享的(可以通過attachment來傳遞數據)。就這么看來,其實在suspend的時候所有的資源都被釋放了,僅僅只是保存了請求來源信息在隊列中,在后續被喚醒的時候再次模擬請求,由業務代碼在實現中判斷是否是第一次進入,并且在不同進入時請求處理過程做差異化實現,最終將不同的邏輯通過不同階段的重入判斷來分階段處理。

             Jetty有兩個技術優化點:

    1.split buffersjetty6 采用split buffer架構和動態buffer分配架構。一個idleconnection沒有buffers分配給他,一旦請求收到,則會有小的請求頭buffer會被分配。大部分都是小請求,則只需要分配消息頭buffer,當發現有大數據內容的時候則分配大buffer.當在等待回寫數據到response的時候,輸出緩存不會被分配。只有當servlet開始寫入數據到response的時候,輸出緩存才被分配,只有當response被提交的時候,response的消息頭緩存才被分配,并且寫出到輸出緩存,有效的執行寫操作。總的來說分配緩存只有在他們需要的時候,而且是根據需求分配

    2.延時分發。支持用異步io讀取內容,延時分發請求到處理器,減少在處理器等待的時間。(簡單來說就是等到read了才去調用服務處理,避免無謂的資源等待浪費)

             TOMCAT

             Tomcat采用的與Jetty不同的設計方式,它的Comet是事件驅動的。每一個傳統的Servlet需要實現CometProcessor接口,這個接口就需要實現類似于原來servletserviceevent方法,event方法會在各種事件發生的時候被激發,event當前主要包含了整個處理的生命周期(begin,close,error,read)。

             需要注意的是在Tomcat配置connector的時候必須選擇apr或者nioconnector,否則是不生效的。可以看到,就和NIO一樣,對于連接建立,數據可讀,都是基于事件觸發,將業務和具體的連接分開,提高在業務處理較慢的情況下,服務器的吞吐能力。這種設計是比較貼近于NIO的設計思想的。

             上面介紹的都是服務端的異步處理,在客戶端其實也需要實現異步化的處理模式,通常情況況下都是基于事件模型實現的。服務端和客戶端如何在異步的情況下理解消息的來源,一種是通過默認消息發送和接收保持順序一致的方式,另一種就是通過頒發消息會話號來實現。

             到此為止都是對于技術的介紹,沒有實質性的使用,后續會根據TOP的實際應用場景去嘗試改造(主要采用jetty或者Tomcat來實施),并作壓力測試,最終得出實際的使用結果,來判斷技術的成熟度。

    posted on 2010-04-20 08:50 岑文初 閱讀(4240) 評論(1)  編輯  收藏

    評論

    # re: 異步模式下的Web請求(技術介紹篇) 2010-04-20 23:49 X-Spirit
    樓主寫的很好。學習了!  回復  更多評論
      


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


    網站導航:
     
    主站蜘蛛池模板: 免费高清资源黄网站在线观看 | 国产真实伦在线视频免费观看| **一级一级毛片免费观看| 日韩免费高清大片在线| 9久9久女女免费精品视频在线观看 | 国产亚洲成av人片在线观看| 亚洲视频网站在线观看| 亚洲欧美成人av在线观看| 国产精品免费视频观看拍拍| 1000部无遮挡拍拍拍免费视频观看| 亚洲精品免费在线观看| 理论亚洲区美一区二区三区| 久久久久国产免费| 四虎影视免费永久在线观看| 99亚洲精品高清一二区| 国产精品免费αv视频| 中文字幕亚洲一区二区三区| 亚洲色大成网站www| 久久久久久久岛国免费播放| 亚洲黄色网站视频| 免费无码AV片在线观看软件| 久久亚洲免费视频| www一区二区www免费| 久久精品国产96精品亚洲| 色爽黄1000部免费软件下载| 国产福利在线免费| 免费无码AV一区二区| 成年女人毛片免费播放视频m| 亚洲国产一区国产亚洲 | 污污视频免费观看网站| 亚洲Aⅴ无码专区在线观看q| 手机在线看永久av片免费| 色婷婷六月亚洲综合香蕉| 欧美男同gv免费网站观看| 日本特黄特色AAA大片免费| 亚洲精品免费观看| 国产又大又黑又粗免费视频| 永久免费AV无码网站国产| 亚洲熟女乱综合一区二区| 国产偷国产偷亚洲高清人| 成人免费毛片观看|