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