針對在項目中碰到的一些容錯設計問題,團隊最近進行了一次技術沙龍,討論瞭如下話題。node
爲何須要應用層的容錯設計?redis
一個完整的系統在內部是由不少小服務構成,服務之間以及服務與資源之間會存在遠程調用。服務器
每一個系統的可用性不可能達到100%網絡
各類網絡及硬件問題,如網絡擁堵、網絡中斷、硬件故障……多線程
遠程服務平均響應速度變慢負載均衡
服務器平均響應速度若是慢下來,慢慢消耗掉系統全部資源,進而致使整個系統不可用。所以在分佈式系統中,除了遠程服務自己須要有容錯設計以外,在應用層的遠程調用的環節,須要有良好的容錯設計。框架
應用層的容錯設計有哪些方法?如下是微博團隊使用過的一些實踐。異步
訪問MySQL的容錯設計async
寫操做:若是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層來一勞永逸?不過這個需求不是twitter幹過嗎?
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.
在Twitter體系,分佈式服務能夠從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……