链路追踪技术的应用及实践
分布式架構的興起推動了一些新技術的發展。其中鏈路追蹤技術以其在APM領域的優異表現,成為了分布式架構中不可或缺的一部分。在本文中,我們將談談它的一些經典應用場景,以及筆者所在的團隊如何利用鏈路追蹤技術提升團隊的研發效能。
一、鏈路追蹤背景
如圖所示,在微服務體系中,一個請求往往需要多個服務協作處理。
?
凡事有利必有弊,這種模式在給我們帶來更好的可擴展性的同時,也帶來了一些新的問題。例如,排查問題的困難:任意節點的異常都可能導致上游鏈路的異常,難以追根溯源;系統拓撲復雜難以把控,健壯性存在隱患。
?
2010年,谷歌發表了一篇論文,介紹了谷歌的內部鏈路追蹤系統Dapper的設計,鏈路追蹤技術自此進入社區的視野。
?
下面,我們將簡單介紹其在APM領域的應用,以及在服務依賴治理和研發效能提升方面的實踐。
?
二、APM
?
分布式系統中,一個請求會在多個節點之間流轉,APM通過TraceID將整條請求處理鏈路中的相關節點關聯起來,并記錄每個節點的執行時間等信息,形成請求的生命周期鏈路。
如圖,我們可以很直觀地看到請求經過了哪些節點,以及各個節點的處理耗時。這使得我們在關注服務本身運行狀態的同時,還能從請求生命周期的視角關注到整條請求鏈路上的所有細節及指標,大幅提高了我們排查定位問題的效率。
?
三、服務依賴治理
?
不合理的依賴,可能導致邊緣系統的故障拖垮核心服務,威脅到分布式系統整體的穩定性。通過鏈路追蹤數據的匯總分析,我們可以繪制出系統間的依賴拓撲,為依賴治理提供數據支撐。
?
我們一般會從下面三個角度來評估服務依賴的合理性:
- 反向依賴。反向依賴指高等級服務依賴了低等級服務。例如,租戶服務是我們的核心服務之一,而統計服務重要性相對較低,顯然,我們不允許租戶服務依賴統計服務。通過服務拓撲圖和服務等級的結合,我們可以很容易的將反向依賴分析自動化,實時預警。
- 強弱依賴。強依賴指下游服務發生異常時,將影響當前節點的穩定性。在設計時,我們應該充分考慮強依賴在當前場景中的必要性。強依賴是否可以弱化,如果不能,業務場景是否允許加上熔斷降級之類的的保護措施。強弱依賴的梳理,我們可以結合故障注入工具,產出系統化的報告。
- 環狀依賴。環狀依賴往往是邊界不清晰的表現,絞成一團,層次不清。對環狀依賴的梳理也是我們對業務邊界和系統邊界的梳理,對系統整體健康度的提升非常有意義。
?
?
四、研發效能提升
?
隨著業務的發展,研發團隊的規模在一定階段也會相應地不斷提升,但支撐我們研發活動的基礎設施卻沒有辦法線性增長,這其中最重要的就是聯調或測試環境。
?
業務發展往往導致并行迭代的增多,而這些并行迭代難免會改動到相同的服務,尤其是一些核心基礎服務。如下圖:
這就會導致兩個問題——
?
1.?環境爭奪。如圖,Story-B需要部署ticket服務,與此同時Hotfix-A也等待驗證,同樣需要部署ticket服務,這意味著至少有一方會被阻塞等待,這種串行模式,極大地降低了我們的交付效率。并行迭代越多,效率降低越明顯。
?
2.?環境的穩定性。服務之間是相互聯系的,任何服務的不穩定都可能會導致該環境的不穩定。上圖中的auth服務,幾乎要被所有的業務流程使用。如果Story-A部署auth服務時,重啟/部署的過程不夠平滑,或者Story-A的代碼中存在某些bug,那么會造成整個測試環境的不穩定。
?
項目規模不大時,我們往往能通過一些管理手段來協調。例如版本串行化,通過將迭代計劃錯開,避免在同一個時間段都要去部署某個服務。測試環境只部署特定分支,需要驗證時則將各自的代碼都合并到此分支;要求部署到測試環境的代碼必須達到某種標準以提升測試環境的穩定性。
?
然而我們也可以看到,管理手段的有效性是和團隊規模微服務規模反相關的,我們需要有技術手段來達到更好的效果。
?
細想一下,其實問題的根源是大家共用一套測試環境,所以我們的研發活動出現了資源競爭,我們對某個服務的操作可能影響到其他服務。
?
那么,能否讓大家都能輕松創建各自的環境,且各個環境的使用互不影響呢?
如上圖,Story-A需要部署user和auth服務,那么我們創建env-1并部署我們的user和auth; Story-B需要部署ticket服務,那么我們就創建env-2并部署ticket服務;env-3同理。
?
為了描述方便,我們把上圖中的env-x環境,叫測試環境;圖中的下半部分,叫回歸環境。測試環境只包含本次迭代需要部署的應用,回歸環境包含所有應用。
?
當我們使用這套機制時,我們期望env-1的使用者,請求user和auth服務時只會路由到env-1環境,請求其他服務時路由到回歸環境。env-2環境的使用者,請求ticket服務時只會路由到env-2環境,請求其他服務時同樣路由到回歸環境。
?
也就是說,對于環境使用者的請求,如果相關的應用在該環境內,則請求只會被該環境內的應用處理,否則路由到回歸環境處理。
?
回歸環境是一個包含所有服務的相對穩定的環境,開發和提測不允許在回歸環境部署,以此來保證足夠的穩定性。
?
研發流程方面,我們不再像以前一樣部署到大家都在使用的環境中去驗證,而是各自創建各自獨享的環境,在自己的環境中完成相關工作。
?
我們將上述機制稱之為環境隔離,要實現環境隔離,技術側至少需要實現兩方面的能力:
- 識別并傳遞請求對應的環境信息
- ?預中間件的實例選擇/消費規則
識并傳遞請求對應的環境信
首先,我們需要能將請求和測試環境關聯起來。
?
識別請求對應的環境信息,這意味著我們在創建測試環境時需要指明某種標識,且這種標識我們可以從請求中提取出,從而通過雙方標識的匹配來完成關聯,這種標識可以是用戶賬號、某組IP,或者企業租戶,使用哪種方式不重要,重要的是結合業務特點達到方便易用的目的。
?
例如,在我們的SaaS系統七魚里,我們使用租戶id來作為我們的標識。在我們的平臺創建測試環境時,除了指明要部署的應用外,我們還需要輸入租戶信息,通過這種方式完成請求和測試環境的映射。
我們可以在請求的統一入口處(例如,網關),獲取到請求所屬的租戶,之后我們可以進一步拿到它所屬的環境信息(環境ID、應用列表)。類似于鏈路跟蹤系統在請求鏈中傳輸TraceID,我們在請求鏈中附加上環境信息,為環境隔離打下基礎。
?中間件的實例選擇/消費規則
?
我們以微服務架構中最常用的幾個組件為例,談談環境隔離的實現方式。
?
RPC框架——
?
RPC的核心流程:provider實例將自己注冊到注冊中心,consumer通過注冊中心獲取provider實例列表,根據一定的實例篩選策略和負載均衡算法,選擇其中一個實例發起調用。
?
所以改造的手段很明確,provider啟動時,我們在元數據中寫入環境ID。在實例選擇時,我們從請求的鏈路數據中拿出環境ID與之做匹配。
?
需要特別注意的是,匹配不到符合要求的實例時,我們不能簡單的認為no provider而讓程序報錯,我們需要考慮該provider所屬的應用是否在對應環境應用列表中,如果不在,我們需要將請求路由到回歸環境中。
消息中間件——
RPC在調用之前有如上所述的實例篩選過程,但消息中間件沒有這個邏輯,不過我們依然可以干預消費規則,即在消費者拿到消息后判斷是丟棄消息還是消費該消息。以kafka為例,測試環境的kafka consumer啟動時,修改consumer groupid為groupid_${env}。kafka consumer接收到消息時,執行和上述RPC框架篩選實例時類似的邏輯即可。
定時任務——
定時任務其實最為特殊。前文中我們提到,在請求的統一入口,查詢請求所對應的環境信息并寫入鏈路。但是定時任務發起的請求并不是用戶觸發的,它來自系統內部,定時調度組件才是請求的“源頭”。所以我們需要在定時任務執行之初,就加入我們的判斷標識邏輯,這要求我們:
?
- 定時任務需要有統一的調度平臺,避免各業務模塊姿勢各異,無法由通用組件統一處理
- 針對調度組件的任務分發/分片機制的改造,統一抽象執行層,加入環境隔離邏輯
?
五、結束語
?
在網易智慧企業中,鏈路追蹤技術的應用,提升了我們的問題排查效率以及對請求鏈路的把控,也為服務依賴治理提供了必要的數據支撐。同時環境隔離也極大地提升了交付效率和測試環境的穩定性,從而提高了研發團隊的整體幸福感。
?
整體來說,我們構建了統一的鏈路追蹤體系,支撐了服務依賴治理及環境隔離技術的實現,但這并不是終點,我們還可以發掘更多的場景,比如SaaS系統的多租戶資源隔離,或者異常監控預警。世界很大,一起多探索。
總結
以上是生活随笔為你收集整理的链路追踪技术的应用及实践的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 网易智慧企业 Node.js 实践(3)
- 下一篇: Kafka的原理介绍及实践
