應用層的容錯與分層設計
針對在項目中碰到的一些容錯設計問題,團隊最近進行了一次技術沙龍,討論了以下話題。
為什么需要應用層的容錯設計?
一個完整的系統在內部是由很多小服務構成,服務之間以及服務與資源之間會存在遠程調用。
- 每個系統的可用性不可能達到100%
- 各種網絡及硬件問題,如網絡擁堵、網絡中斷、硬件故障……
- 遠程服務平均響應速度變慢
服務器平均響應速度如果慢下來,慢慢消耗掉系統所有資源,進而導致整個系統不可用。因此在分布式系統中,除了遠程服務本身需要有容錯設計之外,在應用層的遠程調用的環節,需要有良好的容錯設計。
應用層的容錯設計有哪些方法?以下是微博團隊使用過的一些實踐。
訪問MySQL的容錯設計
- 寫操作:如果master異常,直接拋異常。
- 讀操作:如果slave有多個,先選擇其中一個slave,如果獲取連接失敗,再選擇其他的slave,如果全部不可用,最后選擇master。
訪問Memcached/Redis的容錯設計
首先設置so_timeout,避免無限制等待;服務器連接如果IO異常,設置錯誤標志,一段時間停止訪問;出錯后定期主動(比如ping Redis)或被動(當被再次訪問時)探測服務是否恢復。
Failover機制:
如果連接某個node失敗, 當前pool啟用一致性hash切換到backup node;如果backup node沒有數據,則通過另外一個服務池(數據副本)獲取數據。
訪問遠程HTTP API的容錯設計
設置so_timeout;部分場景:短超時,重試一次;另外由于HTTP service情況的多樣性,業務層面還有通用的降級機制。
訪問不同資源使用不同方法存在的問題
從上面列舉的部分場景來看,在訪問不同資源時候,每種client訪問都有一些相通的原理,但卻要使用不同的重復實現。由于各個client獨立實 現,實現時候由于各個遠程服務協議及行為的差異,導致這些容錯原理無法直接復用。另外在代碼層面,不同的client也使用了不同年代的一些底層庫,一些 早期client的實現,數據層,連接層,協議層全部耦合在一起,也造成維護成本進一步加大。
比如之前一些服務開發中碰到的類似如下的問題:
- hbase-client由于沒有實現容錯設計,導致訪問出現了抖動,影響了同一服務池的其他調用,需要增加類似MySQL client的容錯及快速失敗策略;
- MySQL slave流量出現不均衡了,由于多個slave IP之間沒有使用公用的負載均衡策略,因此需要重新添加、上線及驗證。
另外目前分布式系統中大部分遠程資源都是IO bound而不是CPU bound,而client大部分又是同步調用,造成大部分調用都在等待遠程返回,同時也消耗了工作線程資源,以及大量線程context switch。
有沒有可能統一的client?
這些策略原理上是可以公用的,能否出一個統一的client層來一勞永逸?不過這個需求不是推ter干過嗎?
Finagle,不僅是平時理解的RPC框架,還有目標是想成為一個commons client,從另外一個層面,廣義上訪問遠程資源也都可以理解成RPC,所以Finagle也常稱為RPC框架。
Finagle implements uniform client and server APIs for several protocols, and is designed for high performance and concurrency.
在推ter體系,分布式服務可以從future, service, filter三個層次理解,容錯、超時、授權、tracing、重試等機制都是體現在filter中;而future則將client從多線程、隊列、連 接池、資源管理釋放出來,從關注控制流到關注數據流。并且默認變成異步方式。
Finagle的FailFast模塊會避免分發請求到出現問題的服務,它通過來記錄到每個host的錯誤來進行標記,當出錯以后,Finagle會通過一個后臺線程定期重連以檢查是否恢復。當host宕機時,相關的service會標記成不可用。
如果來redisign一個通用的網絡client,它應該包括哪些元素?
- 具有服務的分層設計,借鑒Future/Service/Filter概念
- 具有網絡的分層設計,區分協議層、數據層、傳輸層、連接層
- 獨立的可適配的codec層,可以靈活增加HTTP,Memcache,Redis,MySQL/JDBC,Thrift等協議的支持。
- 將多年各種遠程調用High availability的經驗融入在實現中,如負載均衡,failover,多副本策略,開關降級等。
- 通用的遠程調用實現,采用async方式來減少業務服務的開銷,并通過future分離遠程調用與數據流程的關注。
- 具有狀態查看及統計功能
- 當然,最終要的是,具備以下通用的遠程容錯處理能力,超時、重試、負載均衡、failover……
來自:http://timyang.net/service/application-failure-managment/