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