摘要:
以淘寶為例,剖析微服務(wù)應(yīng)用故障定位系統(tǒng)實(shí)現(xiàn)原理!
當(dāng)下最流行的設(shè)計(jì)架構(gòu)便是微服務(wù)架構(gòu),越來越多的企業(yè)將老的服務(wù)拆分成微服務(wù)模式、在新的業(yè)務(wù)中采用微服務(wù)架構(gòu)的設(shè)計(jì)理念進(jìn)行技術(shù)架構(gòu)設(shè)計(jì)。 其中實(shí)踐的最好的莫過于阿里了,早期淘寶的架構(gòu)是一個單體式架構(gòu),即Linux操作系統(tǒng)+apache服務(wù)器+mysql數(shù)據(jù)庫+PHP開發(fā)的程序,所有的功能如用戶注冊與管理、商品管理、訂單管理全都集中在一個程序包里,業(yè)務(wù)越擴(kuò)展越大,這個程序包也變得越來越大,最終長成了巨無霸應(yīng)用,難以承受業(yè)務(wù)的繼續(xù)增長,技術(shù)團(tuán)隊(duì)也難以進(jìn)行維護(hù)。
不過辦法總比困難多,在千百個日夜輪回的摸索與實(shí)踐后,終于找到了合適的解決方案,即進(jìn)行重構(gòu),將原來的巨無霸應(yīng)用進(jìn)行業(yè)務(wù)抽象,拆分成獨(dú)立的子服務(wù),由不同的團(tuán)隊(duì)進(jìn)行開發(fā)與維護(hù)。
以淘寶的體量來看,該應(yīng)用足以拆分上千個子業(yè)務(wù),下圖是2012年淘寶的整個服務(wù)調(diào)用拓?fù)鋱D,如果到2020年,那么業(yè)務(wù)必定會更加的復(fù)雜。
不只是淘寶會有這么復(fù)雜的微服務(wù)鏈路,任何一個企業(yè),只要采用微服務(wù)架構(gòu)的模式進(jìn)行技術(shù)架構(gòu)設(shè)計(jì),勢必都會產(chǎn)生復(fù)雜的鏈路調(diào)用,也勢必都會面臨著著四個問題:
1)定位故障難。當(dāng)客服向你反饋用戶無法進(jìn)行下單時,很難去排查故障原因。表面上只是一個簡單的下單操作,背后卻是由幾十個微服務(wù)所構(gòu)成的,而且是由不同的業(yè)務(wù)團(tuán)隊(duì)進(jìn)行開發(fā),出現(xiàn)問題了需要牽扯十幾個部門一起排查,定位故障及根本原因太難了。
2)規(guī)劃容量難。對于服務(wù)平臺來說,隔三差五的搞個活動、做個促銷啥的再正常不過了,一般搞大活動之前都會對業(yè)務(wù)進(jìn)行壓測,制定本次活動的機(jī)器資源安排,然而測試環(huán)境與生產(chǎn)環(huán)境情況并不完全一樣,每個服務(wù)的參與程度、重要性都是不一樣的,規(guī)劃合適的容量太難了。
3)梳理鏈路難。在當(dāng)下,互聯(lián)網(wǎng)企業(yè)的人員流動是非常正常的事情,往往一個系統(tǒng)的從開發(fā)到完成經(jīng)歷了多個人的手,只有從頭到尾全參與的人才知道系統(tǒng)的技術(shù)架構(gòu),核心人員流動后對于系統(tǒng)的架構(gòu)梳理、性能優(yōu)化就變得非常難了。一個剛?cè)肼毜男氯送ū容^久的時間才能梳理清楚業(yè)務(wù),才能在業(yè)務(wù)開發(fā)的時候處理得當(dāng),不影響上下游業(yè)務(wù)。
4)浪費(fèi)資源多。由定位故障難產(chǎn)生的人力成本、規(guī)劃容量難產(chǎn)生的機(jī)器資源成本、梳理鏈路難產(chǎn)生的人力成本導(dǎo)致了企業(yè)資源的浪費(fèi)。
這些都是實(shí)行微服務(wù)架構(gòu)帶來的問題,那微服務(wù)架構(gòu)問題這么多?難道是要讓我們不用它了嗎?
其實(shí)不然,有了問題就必然會有解決方案。一套完整的微服務(wù)解決方案也必然包含故障定位部分,那么業(yè)內(nèi)是如何來實(shí)現(xiàn)微服務(wù)的故障定位呢?
目前業(yè)內(nèi)的解決方案一般包含三個模塊,即數(shù)據(jù)采集、數(shù)據(jù)分析、數(shù)據(jù)呈現(xiàn)。
數(shù)據(jù)采集是在應(yīng)用的每個服務(wù)上安裝探針,當(dāng)服務(wù)的進(jìn)程啟動時,該探針也會啟動,采集服務(wù)運(yùn)行中的數(shù)據(jù)。
數(shù)據(jù)分析是通過收集的數(shù)據(jù)獲取鏈路調(diào)用關(guān)系、程序執(zhí)行情況。
數(shù)據(jù)呈現(xiàn)即在前端頁面呈現(xiàn)鏈路拓?fù)?、服?wù)執(zhí)行情況。研發(fā)人員通過前臺就可知道整個服務(wù)鏈路情況、程序運(yùn)行情況,快速定位故障根因,完美解決了微服務(wù)架構(gòu)的四大問題!
目前用的最多的應(yīng)用基本是java語言開發(fā)的,因此我們以java應(yīng)用來進(jìn)行講解整個監(jiān)控系統(tǒng)的實(shí)現(xiàn)。
我們知道java程序都是在JVM中運(yùn)行的,實(shí)質(zhì)上是將java代碼編譯成的class文件,jvm做的第一件事情便是通過java.lang.ClassLoader去加載類(比如A.class),此時探針agent會截取A.class類嵌入監(jiān)控代碼生成A’.class類,之后所有的用戶請求都會在A’.class類里執(zhí)行,而我們的監(jiān)控代碼把這些都完完全全的記錄下來了,并且定時發(fā)給了后臺。
探針采集了數(shù)據(jù)后需要后臺分析,我們先看一個真實(shí)每天都在上演的業(yè)務(wù)場景,用戶在頁面發(fā)起“添加購物車”、“從購物車刪除商品”、“從購物車進(jìn)入商品結(jié)算”等等,其實(shí)整個系統(tǒng)運(yùn)行的每一秒都在發(fā)生著N個用戶請求,每個請求的鏈路調(diào)用請求不完全一致,對于添加購物車服務(wù)來說:購物車服務(wù)B調(diào)用用戶服務(wù)C、C調(diào)用商品服務(wù)D;對于從購物車刪除商品來說:購物車服務(wù)B調(diào)用商品服務(wù)D、商品服務(wù)D調(diào)用商品庫存服務(wù)E;對從購物車進(jìn)入商品結(jié)算來說,購物車服務(wù)B調(diào)用結(jié)算服務(wù)E、支付服務(wù)F….就這短短的一秒鐘,產(chǎn)生了B->C->D、B->D->E、B->E->F….的服務(wù)鏈路,如果其中的某次調(diào)用C->D出了問題,那么B系統(tǒng)的研發(fā)人員完全不知道問題出現(xiàn)在哪里了。這個時候我們要引入兩個專業(yè)的名詞spanid、traceID。
對于故障問題的定位,通過traceID就可以進(jìn)行跟蹤。用戶的請求一發(fā)起,我們就給它打上了traceID的標(biāo)簽,隨著這個請求繼續(xù)的往后面發(fā)生調(diào)用,traceID就繼續(xù)跟著到了下游系統(tǒng)中,一直到請求的調(diào)用執(zhí)行完成,而所有的執(zhí)行都會記錄在日志中。當(dāng)某次調(diào)用發(fā)生錯誤時,我們只要獲取到這個traceID,在整個日志中進(jìn)行搜索,就可以知道它卡在哪里了,找到了問題的根本原因。
對于調(diào)用鏈路的梳理,通過spanID就可以進(jìn)行還原。當(dāng)整個用戶請求開始發(fā)生時,我們把第一次鏈路的調(diào)用賦值為0,每深入一次就疊加一次,比如B->C->D中,B->C是0.1、C->D是0.1.1;每進(jìn)行一次同深度的調(diào)用再自加一次,比如B->D->E中,B->C是0.2、C->D是0.2.1。后臺系統(tǒng)通過上萬筆的調(diào)用鏈路分析處理,最終會給到一個鏈路調(diào)用拓?fù)鋱D
因?yàn)楸O(jiān)控代碼在代碼的執(zhí)行都進(jìn)行了埋點(diǎn),所以通過代碼開始和代碼結(jié)束的時間戳對比就能獲取到整個代碼執(zhí)行的時間和次數(shù),進(jìn)而獲取到用戶請求的執(zhí)行時間和執(zhí)行次數(shù),再進(jìn)而獲取到服務(wù)的執(zhí)行時間和執(zhí)行次數(shù),再再獲取到整個應(yīng)用的執(zhí)行時間和執(zhí)行次數(shù),后臺把數(shù)據(jù)處理好了之后傳遞給到前端,就可以呈現(xiàn)給到用戶整個微服務(wù)應(yīng)用的執(zhí)行情況了,程序員哥哥們再也不用擔(dān)心微服務(wù)應(yīng)用的故障問題找不到,天天996了。
只談微服務(wù)架構(gòu)的設(shè)計(jì),而不談其出現(xiàn)的問題與解決方案便是耍流氓。
在微服務(wù)架構(gòu)時代,對于整個系統(tǒng)的監(jiān)控、調(diào)用鏈路的追蹤、服務(wù)的熔斷限流等機(jī)制都是必不可少的。
工欲善其事,必先利其器。隨著云計(jì)算、5G、人工智能等的普及應(yīng)用,容器技術(shù)、Devops的廣泛應(yīng)用,微服務(wù)必定是會大放異彩,而其背后的助力無疑是整個監(jiān)控系統(tǒng)~