微服務在實踐中的難點,小米消息推送是如何做的?
小米推送技術負責人夏超在Qcon全球軟件開發大會專場上發表演講—《微服務在小米消息推送的演進》。通過對小米消息推送的真實案例分享,全面介紹了微服務在具體實踐中的關鍵技術難度和痛點,以及我們的一些具體做法。
以下是小編整理出來的夏超老師分享的內容,如果你沒有到現場聽講或是想再加深一遍印象,請往下滑動閱讀。
微服務化的動機和挑戰
原有的單體服務隨著業務的發展,模塊越來越多,之間的耦合越來越高,嚴重影響系統的可擴展性,也極大影響團隊開發的效率。我們需要將模塊做某種程度上重組,即將模塊以服務的形式獨立出來。一個請求從原來的單個進程中的函數調用,變成了多個進程間的網絡通信。由于增加了網絡這個不確定性,如何保證系統整體的穩定性,如何在橫跨多個服務調用的情況下能夠快速的定位和排查問題就成了系統微服務化帶來的主要挑戰。我們的應對方法就是需要做服務治理。
服務管理
服務的信息通過人工方式進行注冊,路由中心通過服務的實例的上報狀態來生成路由表。服務的管理主要有以下兩點。首先是服務的限流:主要是為了防止擁塞向前傳導。其次是服務的發布和升級,必須考慮灰度控制,灰度策略比較靈活(實例級別的,流量級別的和自定義級別的),灰度的策略通過配置中心進行控制。
路由管理
單個集群的路由負載策略是以服務端為主,客戶端為輔的做法。服務端的策略是基于實例權重,客戶端策略延時自適應的做法。以服務端為主是考慮系統的穩定,也是中心化思想的體現,但也有缺點,就是不能夠及時完整的反映路由的情況。當然路由調度中一個重要的點是要防止系統發生雪崩,在這方面采用了服務端和客戶端相結合的保護策略。
多個集群之間按照不同的方式合成路由表,提供了跨集群調度的能力,其中包括:多個集群權重混合模式、互備模式和過載保護模式。
鏈路監控
傳統的監控是機器實例粒度的,當請求調用很深時,一旦下游發生問題,整個系統會產生大量的關聯報警,嚴重影響對問題的定位。所以需要對傳統的監控升級,改造成基于鏈路的監控,提高系統的可診斷性。
上圖就是一個實例:如果入口服務X發生報警,那么查看整個調用鏈,找到問題的源頭,如這里就是Z1->G0的服務出了問題才導致的整個鏈路報警。然后根據Z1->G0的調用情況分布(出問題的調用是否集中分布于某臺機器,某個機房,錯誤碼的分布情況),來判斷問題產生的原因。實踐表明,通過錯誤分布分析,一般能夠排除90%左右的問題。剩下就要具體查看失敗請求的調用鏈來調查問題。
由于在我們的消息系統中,調查問題需要全采樣,傳統的Zipkin集中式調用鏈解決方案需要消耗大量的存儲和帶寬,通過改造,將trace的存儲分散在各個機器上面,并結合日志系統來保存調用鏈信息。查找的時候,首先在入口機器上面都搜索一遍,然后根據trace的調用上下游,到下游機器上逐個查找,完成trace的拼接。
有狀態服務的改造
一般微服務都是針對無狀態服務的,而消息推送服務中,有很多服務本身是有狀態的,比如登錄狀態服務,離線消息服務等。我們需要將這些有狀態服務業納入我們的統一服務治理中。
有狀態服務主要考慮服務數據的遷移(擴容縮容都屬于數據遷移),我們的做法是定義數據分布的兩張視圖,遷移前和遷移后的,然后在上面定義各種遷移的狀態來控制上游的讀寫。舉例來說,如下圖,現在要遷移PARTITION 3的數據從BASE0數據分片到BASE1數據分片。定義了如下狀態:
熱數據遷移:上游數據對PARTITON 3數據的讀采用雙讀,寫入BASE1。
冷數據遷移:維持上游的讀寫狀態,將BASE0上未遷移的數據遷移到BASE1上。
完成遷移:上游數據對PARTITON 3數據的讀寫均發往BASE1。
總結與感悟
對消息推送系統的微服務化改造,我們的感悟總結以下幾點:
1.壞消息傳播的慢:限制問題的擴大。比如限流,熔斷等策略。
2.壞消息發現的快:快速發現和定位問題。鏈路監控和鏈路調查極大提升系統的可診斷性。
3.自動化本身有代價:比如出現極端情況,簡單的人工流量調度比一個需要考慮各個極端情況的***自適應算法更有效。
4.大型系統的微服務治理的順序是:穩定,易用,高效。