1. 程式人生 > 實用技巧 >spymemcached原始碼中Reactor模式分析

spymemcached原始碼中Reactor模式分析

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

簡介

spymemcached 是一個 memcached 的客戶端, 使用 NIO 實現。採用Reactor模式實現,單執行緒,高效能Memcached客戶端。

spymemcached原始碼分析:http://my.oschina.net/astute/blog/93492

Reactor模式介紹

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

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

經典網路服務接受客戶端請求,響應請求過程可以抽象為以下步驟:

  1. 讀取請求資料 : read
  2. 解碼資料: decode
  3. 計算:compute
  4. 編碼資料:encode
  5. 傳送資料:send

網路服務所有動作被抽象為這個五個步驟的handler;可能每個handler有單獨執行緒執行,或者由一個執行緒順序執行;

這種經典設計中存在以下問題:

  1. 每個連線分配一個執行緒,而每個連線傳送請求資料較少,導致大量空閒執行緒;
  2. 大量執行緒上下文切換和鎖競爭

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


  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返回最終資料的原因。


轉載於:https://my.oschina.net/yychao/blog/99873