spymemcached源碼中Reactor模式分析

簡介

spymemcached 是一個 memcached 的客戶端, 使用 NIO 實現。採用Reactor模式實現,單線程,高性能Memcached客戶端。 java

spymemcached源碼分析:http://my.oschina.net/astute/blog/93492 react

Reactor模式介紹

所謂reactor模式,實際上是event-driven pattern在網絡服務設計中的應用,以平衡CPU與IO速率,最大化CPU資源與IO資源的利用率; tomcat

先來看看經典的服務器設計: 服務器

經典網絡服務接受客戶端請求,響應請求過程能夠抽象爲如下步驟: 網絡

  1. 讀取請求數據 : read
  2. 解碼數據: decode
  3. 計算:compute
  4. 編碼數據:encode
  5. 發送數據:send

網絡服務全部動做被抽象爲這個五個步驟的handler;可能每一個handler有單獨線程執行,或者由一個線程順序執行; 多線程

這種經典設計中存在如下問題: 異步

  1. 每一個鏈接分配一個線程,而每一個鏈接發送請求數據較少,致使大量空閒線程;
  2. 大量線程上下文切換和鎖競爭

爲了解決上述問題,採用兩個方法實現: memcached


  1. 採用分治的思想,將鏈接劃分爲更小粒度的非阻塞任務:將用戶鏈接劃分爲 多個用戶請求,每一個請求一個線程處理;減小 請求間空閒時間佔用線程
  2. 採用事件處理模式,分派可執行任務;經過IO 事件觸發 handler 處理


採用事件處理模式的單線程Reactor模式: 源碼分析

單線程Reactor 處理 鏈接請求,全部用戶請求都在同一個線程中;經過IO事件觸發相應的操做;IO事件觸發機制可參考java nio機制; 性能

單線程版本的Reactor模式,還有如下問題:

  1. 觸發事件處理 與 處理事件 在同一個線程中;減緩了Reactor的事件觸發及時性
  2. 全部請求必須等待以前請求中IO操做以外的處理過程
  3. 沒法解決CPU與IO速率不一致問題
  4. 不能有效利用多核優點

爲解決上述問題,採用多線程設計方案的Reactor模式:

多線程版本的Reactor模式,有如下優點:

  1. Reactor能夠快速觸發handler執行
  2. IO操做之外操做由線程池中線程獨立處理
  3. Reactor 線程滿負荷 IO操做
  4. 平衡CPU 與 IO 速率

reactor模式就介紹到此,具體看下spymemcached中reactor模式的應用吧

spymemcached中Reactor模式實現

spymemcached中reactor模式設計到如下概念:

  1. IO線程:MemcachedConnection 負責處理
  2. 工做線程:調用spymemcached操做的線程;一般是應用線程,例如tomcat線程等等;

工做線程職責:

  1. 經過MemcachedClient提交操做請求給MemcachedConnection
  2. MemachedClient提交操做過程:實例化異步操做回執OperationFuture(該回執都會實例化一個CountDownLatch(1));經過OperationFactory 生成定製Callback操做的Operation對象;將Operation操做加入對應ShardedNode 的inputQ;返回異步結果回執OperationFuture對象
  3. 調用OperationFuture對象的get操做阻塞在CountDownLatch,等待後臺IO線程,調用countDown;

IO線程職責:

  1. 由MemcachedClient初始化啓動後臺MemcachedConnection 線程,接受工做線程提交操做:從inputQ拷貝到writableQ;發送操做請求到Memcached服務器;添加操做到readQ,並把操做從writableQ刪除;修改監聽IO事件
  2. 執行select操做,獲取感興趣IO事件
  3. 執行handleIO處理:根據SelectKey發生事件類型:執行讀取操做 or 寫入操做;
  4. 當IO操做完成後,調用Operation Callback對象的receivedStatus設置回執結果;調用countDown釋放阻塞的工做線程;

因而可知,spymemcached Reactor模式實現中,工做線程至關於客戶端請求; IO線程至關於單線程Reactor設計中的Reactor負責接收請求,處理請求;spymemcached對數據解碼部分能夠擴展實現線程池方式提供解碼計算,無需佔用Reactor線程資源,使得Reactor線程滿負荷IO操做和事件觸發;


在spymemcached的Reactor設計中:

MemcachedClient負責接收請求

MemcachedConnection負責處理IO請求

同時還能夠擴展支持線程池TranscodeService對解碼計算提供異步線程支持; 這也是OperationFuture.get()返回值仍未一個Futrue,內部再次調用future.get返回最終數據的緣由。

相關文章
相關標籤/搜索