《持續演進的Cloud Native: 原原生架構下的微服務最佳實踐》
王啓軍/著 (公衆號:奔跑中的蝸牛)
電子工業出版社
2018.10出版
Cloud Native的組成
Cloud Native需要從架構、研發流程和團隊文化三個角度來實現,三者需要相互配合,缺一不可。
-
架構
Cloud Native是以雲和微服務架構爲基礎,雲包含了敏捷基礎設施及公共基礎組件。同時還需要考慮架構的質量屬性。 -
研發流程
自動化的研發環境是Cloud Native的基礎。儘量減少測試及運維對開發的協助,最好由全棧工程師獨自快速交付。 -
團隊文化
一切以人爲主,需要建立自由開放的環境。高度信任,增強自我驅動。微服務架構要求小團隊具有自主決策的權力,避免無論大事小事都要拿到會議上討論,造成決策瓶頸。
Cloud Native成熟度模型
Cloud Native的原則
- 爲失敗設計原則
接受出問題是必然的這個現實,架構中能夠容忍故障的發生,最小化故障的影響範圍。 - 不變性原則
每個服務或組件在安裝、部署完成後將不會發生更改,如果更改在丟棄老的部署新的。 - 去中心化原則
不會因爲一個節點的故障導致整個系統不可用,研發流程上做到關注點分離。 - 標準化原則
一旦系統規模變大,做到標準化是無法避免的。所謂獨立自主是在一定的標準下實現。 - 速度優先原則
當速度和效率發生衝突時,速度優先。 - 簡化設計原則
如果你發現設計滿足了所有的要求,說明你一定過度設計了。 - 自動化驅動原則
只有真正擁抱自動化才能做到持續發佈,才能做到更好的用戶體驗。 - 演進式設計原則
架構是持續演進的,不要一蹴而就。
可用性設計
可用性和可靠性的關係
- 可用性(Availability)是關於系統可以被使用的時間的描述,以丟失的時間爲驅動(Be Driven by Lost Time)
- 可靠性(Reliability)是關於系統無失效時間間隔的描述,以發生的失效個數爲驅動(Be Driven by Number of Failure)
計算公式
- Availability = Uptime / ( Uptime + Downtime )
- Reliability = MTBF / (MTBF + MTTR)
MTFB: Mean Time Between Failure 平均無故障工作時間,指上一次故障恢復後開始正常運行到這次故障的時間平均值。
MTTR: Mean Time To Repair 平均故障恢復時間,指從初心故障到完全恢復的這段時間。
可用性的衡量標準
可用性通常以N個9的方式來量化。
可用性等級 | 可用性百分比 | 年度停機時間 | 可能會用到的技術 |
---|---|---|---|
基本可用 | 99% | 87.6小時 | 簡單的負載均衡 |
較高可用 | 99.9% | 8.8小時 | 灰度發佈、自動化發佈、自動化測試、快速回滾 |
高級可用 | 99.99% | 53分鐘 | 微服務、中間件自動擴展、容錯、監控、彈性伸縮 |
極高可用 | 99.999% | 5分鐘 | 異地多活、智能運維 |
什麼降低了可用性
- 發佈
- 故障
- 壓力
- 外部強依賴
大型網站典型故障案例
- 寫日誌過多
- 高併發訪問數據庫
- 緩存故障
- 應用啓動不同步
- 大文件讀寫獨佔磁盤
- 濫用生產環境
- 不規範的流程
- 不好的編程習慣
發佈方案
- 影子測試:在生產環境通過流量複製、回放和比對的測試方法。
- 負載均衡日誌回放
- TCPCopy
ngx_http_mirror_module、tcpcopy、GoReplay 原名gor、滴滴 rdebug
- A/B Testing: 業務場景並行
- 藍綠部署:系統羣並行
在生產環境額外冗餘一份相同的環境。測試通過後,可用把負載均衡/反向代理/路由從藍色環境指向綠色環境。需要回退直接切整體環境。 - 灰度發佈/金絲雀發佈:部署實例新舊版本並行
在原有版本可用的情況下,同時部署一個新的版本作爲“金絲雀”,測試新版本的性能和表現,以保證在整體系統穩定的情況下,儘早發現問題並解決問題。
容錯設計
- 消除單點
- 特性開關
- 服務分級
- 降級設計
- 超時重試
- 隔離策略
- 熔斷器
降級設計
- 關閉功能
- 請求短路
- 簡化流程
- 延遲執行
超時重試技術考慮點
- 超時時間
- 重試次數
- 間隔時間
- 間隔時間衰減度
超時重試技術方案
- 簡單重試模式:try-catch-redo
- 策略重試模式:try-catch-redo-retry strategy
- 基於spring-retry:
- 基於Guava-retrying
服務隔離策略
- 線程池隔離
- 進程隔離
- 集羣隔離
- 用戶隔離
- 租戶隔離
限流算法
- 固定窗口算法 (fixed window)
- 漏桶算法(Leaky Bucket)
- 令牌桶算法(token bucket)
漏桶算法和令牌桶算法的對比
漏桶算法 | 令牌桶算法 |
---|---|
不依賴令牌,不保存令牌 | 依賴令牌 |
如果桶滿了,則丟棄數據包 | 如果桶滿了,則丟棄令牌,不丟棄數據包 |
不允許突發,恆定速率 | 允許突發 |
限流技術方案
- Guava限流
- Nginx限流
- waf限流
性能設計
常見的性能問題
- 內存泄漏:內存耗盡
- 過載:突發流量,大量超時重試
- 網絡瓶頸
- 阻塞:無盡的等待
- 鎖:通過限制
- IO繁忙:大量的讀寫
- CPU繁忙
- 長請求擁塞:連接耗盡
性能目標
- 響應時間 latency
- 吞吐量 throughput: QPS
- 負載敏感度
- 可伸縮性
性能目標案例
- 響應時間:99%<1s
- 吞吐量大於10萬TPS
- 系統數據量:10億>訂單表>1億
- 數據增長速度:1億/年
- 資源限制:服務器、配置、網絡
如何定位瓶頸
- 壓力測試
- 日誌分析
- 監控工具
性能優化方向
- 服務通訊優化
- 消息中間件
- 緩存
- 數據庫優化
服務通訊優化
- 同步轉異步
- 阻塞轉非阻塞
- 序列化
可擴展性設計
AKF擴展立方體
描述 | 場景 | 優勢 | 挑戰 | |
---|---|---|---|---|
X軸 | 通常稱爲水平擴展,通過複製實例,前端對流量進行負載均衡,從而分攤整體壓力 | 產品初期 | 架構簡單,只需要負載均衡 | 有狀態的服務不容易擴展 |
Y軸 | 根據服務或者資源擴展,即從單體服務演進到微服務架構 | 業務邏輯複雜,代碼規模大 | 故障隔離性好,容易實現業務複雜性分解 | 對工具環境依賴高、運維複雜、一致性實現成本高 |
Z軸 | 根據查詢或者計算結果進行拆分。即分片 | 大型分佈式系統 | 突破單張表的數據規模 | 架構複雜、數據遷移負載 |
微服務的缺點
- 增加了服務調用的開銷
- 分佈式系事務
- 調試與服務治理
如何擴
展數據庫
- X軸擴展:主從複製集羣,Master-Slave讀寫分離。
- Y軸擴展:分庫、垂直分表
- X軸擴展:分片(sharding)
- 區間法(Range-Based):一個月一張表
- 輪流法(Round-Robin) :n = K mod N
- 一致性哈希(Consistent Hash)
一致性設計
事務之間的關係可以通過happen-before表達爲如下四種:
- 讀寫
- 寫讀
- 讀讀
- 寫寫
ANSI SQL92標準定義的四種事務隔離級別如下:
- 未提交讀(Read uncommitted)
- 提交讀(Read committed)
- 可重複讀(Repeatable reads)
- 可串行化(Serializable)
Mysql默認事務隔離級別:可重複讀
隔離級別 | 發生髒讀 | 不可重複讀 | 發生幻讀 | 加鎖讀 |
---|---|---|---|---|
未提交讀 | ✓ | X | ✓ | X |
提交讀 | X | ✓ | ✓ | X |
可重複讀 | X | X | ✓ | X |
可串行化 | X | X | X | ✓ |
分佈式事務理論
- Quorum機制
- 租約機制 Lease
- 狀態機 Replilcated state machine
狀態機故障時節點切換算法
- Paxos算法
- Raft算法
Raft算法
Raft算法將Server分爲三種類型:Leader、Follower和Candidate。
- Leader處理所有的查詢和事務,並向Follower同步事務。
- Follower會將所有的RPC查詢和事務轉發給Leader處理,它僅從Leader接受事務的同步。數據的一致性以Leader中的數據爲準實現。
Raft把一致性問題,分解成三個比較獨立的子問題,並給出每個子問題的解決方法:
- 選舉:描述Raft是如何選擇一個leader的,這個部分很受容易理解了。
- 日誌複製:描述Raft的leader是如何把日誌複製到集羣的各個節點上的。
- 安全性:描述Raft是如何保證“State Machine Safety Property”。
分佈式系統的一致性分類
以數據爲中心的一致性模型
- 嚴格一致性 strict consistency
- 順序一致性 sequential consistency
- 因果一致性 causal consistency
- FIFO一致性
以用戶爲中心的一致性模型
- 單調讀一致性 Monotonic-read consistency
- 單調寫一致性 mono-write consistency
- 寫後讀一致性 read-your-writes consistency
- 讀後寫一致性 write-follow-reads consistency
業界常用的一致性模型
- 弱一致性
- 最終一致性 Eventual consistency
- 強一致性 strong consistency
如何實現強一致性
- 兩階段提交 2PC
- 三階段提交 3PC
如何實現最終一致性
- 重試機制
- 本地記錄日誌
- 可靠事件模式
- Saga事務模型
- TCC事務模型
分佈式鎖
- 基於DBMS: 樂觀鎖CAS,悲觀鎖 select for update
- 基於Zookeeper
- 基於Redis: Set if not exists
如何保證冪等性
- 冪等令牌 Idempotency Key
- 寫前檢查
多版本併發控制(MVCC)