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