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