HSJ實現(一)

來源:互聯網
上載者:User
       HSJ基於netty實現。netty作為基於NIO的一個網路架構,因為它良好的效能表現,現在越來越多的應用使用它。HSJ作為一個非同步實現的用戶端,但其又是一個DB操作用戶端,所以面臨的一個棘手問題就是非同步發送請求後必須準確知道服務方執行的結果。作為非同步發送API大致有以下幾種策略(原文參見http://blog.chinaunix.net/space.php?uid=20357359&do=blog&id=3063161摘錄到本文):同步發送API的設計相對簡單,實作類別似於send和recv的介面就可以了,recv阻塞等待應答的到來。但是這樣會使得API的效能受限,除了採用多線程同步API通過並發來提高效能,另外一種方式就是通過非同步發送API實現。

異 步API的好處就是不用阻塞發送執行內容,交由另外一個執行內容進行具體的發送(可以是核心,也可以是另外一個線程),有應答的時候調用預先設定的 callback。通常情況,由於執行callback的線程一般與調用API的線程是不同的。這個時候要注意安全執行緒,以及鎖的處理。同步發送API的訊息互動流程圖:
  1. client    --- message1 --->    server
  2. client    <--- ack1 --- 
              server
  3. client    --- message2 --->    server
  4. client    <--- ack2 --- 
              server
  5. client    --- message3 --->    server
  6. client    <--- ack3 --- 
              server
非同步發送API的訊息互動流程圖:
  1. client    --- message1 --->    server
  2. client    --- message2 --->    server
  3. client    <--- ack1 --- 
              server
  4. client    <--- ack2 --- 
              server
  5. client    --- message3 --->    server
  6. client    <--- ack3 --- 
              server
非同步發送API實現的時候,主要是兩點:1> message的發送沒有前後依賴關係,後面的message發送的時候不用等待前面message的ack。2> 收到應答的時候進行處理,調用設定的callback。這裡面第1點很容易實現,發送線程不停的發送就可以了,但是對於第2點如何判斷收到應答,這個比較麻煩。因為傳統的同步API是阻塞等待對方的應答,對於非同步發送API,需要有一定的機制來獲得應答。後面的幾種非同步發送API的實現方法中,分別採用不同的方式來擷取應答。1. 專門的發送線程,專門的接收線程使用libpcap和libnet編寫過程式的同學對這種模式不會陌生,業務線程或者是專門的發送線程使用libnet直接發送message,接收線程使用libpcap接收並進行處理。這種方法的本質是,通過另外的接收線程同步接收應答。2. event loop線程業務線程構造發送資料,添加到event線程的req_list中。並通過Pipe通知event線程,event線程進行非同步發送,有應答後,調用相應的callback處理。event loop線程中實現訊息的狀態機器讀取,讀取到完整的訊息,進行相應的邏輯處理後,執行設定的callback函數。這種方法的本質是,依靠select, poll, epoll等事件通知API實現,但是在linux下面只能拿到IO就緒事件,而不是IO完成事件,所以需要輔以協議狀態機器,轉化為IO完成事件。3. 後台發送線程業務線程構造發送資料,添加到後台發送線程的req_list中,並通過pthread_cond來通知後台發送線程。後台線程直接進行發送,並檢查是否有應答,如果有應答就進行處理。這種方法的本質是,發送線程每發送1個message,就檢測一些是否有應答到來。具體檢測跟2的一樣,也是通過select等實現。對於HSJ來說,兩種方式的實現:1. 發送請求時入隊列,接收到請求時出隊列;(參見HSClientSeqHandler.java)2. 記錄串連的id,發送請求時加鎖,接收到請求後釋放;(參見HSClientHandler.java)兩種方式各位利弊,我們來一一分析。方式一:1.網路連接有限的情況下,也能保持較好的效能表現。     在大並發請求下,網路連接是爭用最厲害的資源。這種情況下因為沒有互斥操作,串連是共用的,所以不會產生影響。2.因為這種實現方式存在入隊列和出隊列的操作,如果入隊/出隊的元素非常多,就會拖慢整個系統的吞吐。HS4J qps和hs宣傳的qps出入很大,這個是一個重要原因。3.這種方式的容錯性、可靠性不高。一旦出現網路錯誤或執行耗時等問題都會導致出隊列和入隊列對應不起來,導致嚴重錯誤。目前來看一旦出現這種問題很難解決,HS4J就是這種實現方式。方式二:      首先說明一下,netty架構的每一個channel都有一個id,HSJ就是依據這個id來實現方式二方案的。如果你不知道但又想瞭解請訪問netty官網。      1.運行結果很準確,不會出現差錯。      2.如果設定的串連池很小,管理髮送channel隊列就會經常出現lock,導致效能表現很差。但關於這點需要辯證的看待。對於開發人員來講,你的應用需要多少台機器支撐,每台機器每秒的處理請求數最大是多少,應該都瞭然於胸。對於HSJ每台機器的串連池大小設定成這個最大值即可,你會發現HSJ這時的表現會很好。這裡需要說明一點,HSJ是支援你設定初始串連池數和最大串連池數的。最大串連池數設定為此即可。當串連不夠時HSJ會自動增加串連的,直到最大數。當然在訪問低穀期HSJ也會回收關閉這些串連,節約機器資源。       只要串連池大小設定得當,HSJ的qps可以達到很大。               在同等條件下(50個線程,每次發1000次insert請求),HS4J和HSJ的表現對比:HS4J 方式一 100串連池Concurrency 50 threads,repeats=1000,duration=3500ms,tps=14285Concurrency 50 threads,repeats=1000,duration=3407ms,tps=14675HSJ 方式二 100串連池Concurrency 50 threads,repeats=1000,duration=4703ms,tps=10631增大串連池後Concurrency 50 threads,repeats=1000,duration=218ms,tps=229357

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.