《微服務設計》閱讀筆記(十一)規模化微服務
《微服務設計》,Building Microservices,作者Sam Newman,譯者崔力強、張駿,人民郵電出版社,2016年。
筆記中有些內容直接引用原書。
================================================================
第十一章 規模化微服務
1. 故障無處不在
要假定故障會發生,以這種想法來處理每一件事情,為故障做好準備。
2. 多少是太多
不同的系統對容忍的故障程度、系統的響應速度等都是不一樣的,需要根據這些因素選擇技術,需要讓客戶了解不同級別的服務對應的成本。
響應時間/延遲。可以用不同數量的用戶來測量。「我期望這個網站,當每秒處理200個並發連接時,90%的響應時間在2秒以內。」
可用性。服務能出現故障嗎?是24/7服務嗎?
數據持久性。多大比例的數據丟失是可接受的?數據應該保存多久?
3. 功能降級
功能降級的需求要從業務角度出發。
4. 架構性安全措施
架構性安全性措施是一些組合的模式,確保如果事情真的出錯了,不會引起嚴重的級聯影響。舉了一個之前網站由於下游服務響應緩慢導致級聯故障的例子,採取的措施是:正確的設置超時;實現艙壁隔離不同的連接池;實現一個斷路器。
5. 反脆弱的組織
《反脆弱》一書的作者Nassim Taleb認為事物實際上受益於失敗和混亂。Netflix通過引發故障來確保其系統的容錯性。Netflix開源了混亂猴子(Chaos Monkey)、混亂大猩猩(Chaos Gorilla)以及延遲猴子(Latency Monkey)項目,它們分別用於模擬關閉伺服器、關閉可用區以及網路延遲。讓軟體擁抱和引發故障,從失敗中學習。
超時。下游服務超時,等待太長來決定調用失敗,整個系統會變慢。太短會讓正常工作的調用被認為失敗。沒有超時,一個宕掉的下游系統會讓整個系統掛起。要給所有跨進程調用設置超時,並選擇一個默認時間。超時發生,記錄日誌。
斷路器。當對下遊資源的請求發生一定數量的失敗後,打開斷路器,請求會迅速失敗。過段時間再發送檢查,如果下游服務恢復正常則關掉斷路器。一些斷路器實現:Netflix的Hystrix庫(基於JVM),.NET的Polly,Ruby的circuit_breaker mixin。
艙壁。艙壁通過隔離避免級聯故障。在第4節的例子中,就是對不同服務使用了不同的連接池來隔離。還可以使用關注點分離,通過把功能分離成獨立的微服務,隔離故障影響。斷路器也算蜜蜂艙壁的一種自動機制。
隔離。服務間加強隔離,最好能做到上游服務可以允許下游服務離線。
6. 冪等
多次執行同一操作,與執行一次該操作效果相同。使消息的處理成為冪等能減少很多工作量。
7. 擴展
擴展系統的原因:處理失敗;提升性能。
更強大的主機。這是垂直擴展。
拆分負載。單服務單主機模式擴展為多服務多主機模式。
分散風險。不要把雞蛋放在一個籃子里。例如,不要把多個服務放在一台主機上。要考慮SAN的故障,它會引起所有虛擬機不可用。不要讓所有服務運行在同一個數據中心的同一個機架上。了解雲服務商的SLA(Service-Level Agreement)保證,確保和自己的需求相匹配。
負載均衡。使用負載均衡器,有硬體有軟體(如mod_proxy)。能提供SSL終止功能(將HTTPS連接在內部轉換為HTTP連接)的能簡化單個主機運行實例的配置。負載均衡器的配置要和服務的配置一樣通過版本管理系統管理起來,要能自動化應用。
基於worker的系統。該系統也可以像負載均衡一樣分擔負載降低脆弱性。通過待辦作業列表來分配作業到不同的worker,需要一個持久化的消息代理或Zookeeper。
重新設計。前期將精力放在更重要的事情上,當確實有大量負載來了,再去考慮解決,必要時重新設計。
8. 擴展資料庫
服務的可用性和數據的可用性。要意識到二者的區別。
擴展讀取。通過主節點副本可以做到擴展讀取,不過建議先採用緩存(簡單並且性能改善顯著),其次才考慮副本。
擴展寫操作。數據分片解決擴展寫。看看Cassandra、Mongo或者Riak這樣的資料庫系統。
共享資料庫基礎設施。可能引起單點故障。
CQRS。命令查詢職責分離(Command-Query Responsibility Segregation)模式,系統一部分負責獲取修改狀態的請求命令並處理它,另一部分負責處理查詢。內部用於處理命令和查詢的模型是完全獨立的,可以使用不同的服務或在不同的硬體實現,可以使用不同的數據存儲,因此擴展性強。
9. 緩存
客戶端、代理和伺服器端緩存。代理緩存可以用反響代理或CDN;伺服器端緩存可以用Redis或Memcache。
HTTP緩存。cache-control指令,Expires頭部,實體標籤Etag。它們的使用可以參考《REST實戰》。
為寫使用緩存。有爆髮式寫操作或同樣數據可能被寫入多次,後寫式緩存很有作用。
為彈性使用緩存。在服務不可用時可以使用緩存代替一些服務。
隱藏源服務。緩存消失時,如果源服務無法應對大量請求,則不要請求。可以由源服務在後台重建緩存,也可以原始請求快速失敗,避免級聯故障。
保持簡單。避免太多地方使用緩存。
緩存中毒:一個警示。需要了解數據從數據源到終點的完整緩存路徑,從而真正理解它的複雜性以及使它出錯的原因。
10. 自動收縮
可以根據負載趨勢變化來觸發自動收縮,以響應負載。另外,自動伸縮被更多應用於響應故障。
11. CAP定理
一致性(consistency)、可用性(availability)、分區容忍性(partition tolerance),三個中最多只能保證兩個。
犧牲一致性。
犧牲可用性。
犧牲分區容忍性。
AP還是CP。需要根據具體情況權衡。
這不是全部或全不。不同的服務可以是不同的性質,有的是AP,有的是CP,並不是整個系統中的所有服務都保持一致。
真實世界。在真實世界中,無論系統本身如何一致,都難以做到和真實世界的一致。因此,很多情況下,AP系統是最終正確的選擇。
12. 服務發現
服務實例要能夠註冊,其它服務要能夠找到已經註冊的實例。
DNS。可以使用DNS解決方案。更新DNS條目有些痛苦。亞馬遜的Route53做的不錯,但可選的自託管服務中,沒有那麼好的。
13. 動態服務註冊
比DNS更適用於高度動態的環境發現節點。
Zookeeper。被用於很多場景:配置管理、服務間的數據同步、leader選舉、消息隊列和命名服務。Zookeeper能確保數據在多個節點之間安全地複製,並且當節點故障後仍能保持一致性。
Consul。也支持配置管理和服務發現,其殺手級特性之一是提供了現成的DNS伺服器。還具有對節點進行健康檢查的能力。
Eureka。Netflix開源的系統,提供了基本的負載均衡功能,支持服務實例的基本輪訓和調度查找。
構造你自己的系統。可以使用AWS的API來構造。
別忘了人。要有工具能在註冊中心上顯示報告和儀錶盤給人看。
14. 文檔服務
要能生成服務的API文檔。
Swagger。提供的終端用戶體驗不錯,為超媒體核心中的增量探索概念做的很少。
HAL和HAL瀏覽器。Hypertext Application
Language是一個描述公開的超媒體控制的標準。在使用超媒體的話,建議用HAL,沒使用的話建議用Swagger。15. 自描述系統
Martin Fowler提出的人文註冊表方法,有一個地方可以讓人們記錄組織中有關服務的信息,和維基一樣簡單。從活系統中抽取一些數據,形成靜態Web頁面或維基是一個好的開始。
16. 小結
推薦Nygard的書《Release It!》,分享了關於系統故障的故事以及處理它們的模式,對於構建任何規模化系統都強烈推薦。
BrianZhang:《微服務設計》閱讀筆記(一)微服務BrianZhang:《微服務設計》閱讀筆記(二)演化式架構師BrianZhang:《微服務設計》閱讀筆記(三)如何建模服務BrianZhang:《微服務設計》閱讀筆記(四)集成BrianZhang:《微服務設計》閱讀筆記(五)分解單塊系統BrianZhang:《微服務設計》閱讀筆記(六)部署BrianZhang:《微服務設計》閱讀筆記(七)測試BrianZhang:《微服務設計》閱讀筆記(八) 監控BrianZhang:《微服務設計》閱讀筆記(九)安全BrianZhang:《微服務設計》閱讀筆記(十)康威定律和系統設計BrianZhang:《微服務設計》閱讀筆記(十二完結篇)總結軟體開發之路
推薦閱讀:
※《微服務設計》閱讀筆記(六)部署
※《Cloud Native Go》筆記(十一)使用WebSockets
※微服務落地第三課-Spring Cloud Config Client搭建
※《微服務設計》閱讀筆記(十二完結篇)總結
※《Cloud Native Go》筆記(十五)結論