唐文
摘要:分布式系統(tǒng)對(duì)高性能、高可用性、可伸縮要求越來(lái)越高,消息中間件是重要的技術(shù)之一,解決應(yīng)用解耦、異步消息、流量削峰等問(wèn)題。消息中間件松耦合交互方式在系統(tǒng)整體實(shí)現(xiàn)層面會(huì)呈現(xiàn)出復(fù)雜度,多應(yīng)用間業(yè)務(wù)流無(wú)法跟蹤、無(wú)法定位問(wèn)題,需要耗費(fèi)大量的時(shí)間來(lái)查找定位問(wèn)題。該文實(shí)現(xiàn)一種基于消息中間件的調(diào)用鏈跟蹤方法,可視化業(yè)務(wù)流完整的調(diào)用鏈,同時(shí)統(tǒng)計(jì)分析各階段耗時(shí),而且方法對(duì)應(yīng)用程序?qū)崿F(xiàn)“零侵入”。
關(guān)鍵詞:分布式系統(tǒng);消息中間件;調(diào)用鏈跟蹤;服務(wù)跟蹤
中圖分類(lèi)號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2019)30-0054-02
1概述
分布式系統(tǒng)中應(yīng)用部署在不同節(jié)點(diǎn)中,不同的應(yīng)用之間通過(guò)傳遞消息來(lái)激活對(duì)方的事件觸發(fā)相應(yīng)的操作,發(fā)送者將消息發(fā)布到主題中,消費(fèi)者通過(guò)訂閱主題來(lái)獲取關(guān)注的消息,消息中間件能在不同平臺(tái)之間通信,屏蔽掉各種平臺(tái)及協(xié)議之間的特性,實(shí)現(xiàn)應(yīng)用程序之間的協(xié)同。發(fā)布/訂閱者不相互感知,由此帶來(lái)一些問(wèn)題:消息在應(yīng)用程序之間傳遞丟失,無(wú)法快速定位出丟失消息的應(yīng)用嘲;業(yè)務(wù)流過(guò)程中如果出現(xiàn)性能問(wèn)題,無(wú)法快速確定哪個(gè)應(yīng)用耗時(shí)長(zhǎng)。以上問(wèn)題往往需要將各個(gè)應(yīng)用日志打開(kāi),耗費(fèi)大量人力才能找出問(wèn)題。
分布式消息跟蹤業(yè)界已有成熟的實(shí)現(xiàn)方案,代表是GoogleDapper,其實(shí)現(xiàn)原理是:對(duì)于每次用戶發(fā)起的請(qǐng)求,使用一個(gè)TRACE ID作為標(biāo)識(shí),每個(gè)服務(wù)組件使用SPAN ID作為標(biāo)識(shí),服務(wù)組件對(duì)于到達(dá)的請(qǐng)求記錄跟蹤日志,跟蹤日志中包含TRACE,ID、SPAN ID和PARENT,ID(消息發(fā)送上游組件的SPAN加),組件通過(guò)PARENT ID找到上游組件,用戶發(fā)起的請(qǐng)求涉及的所有組件調(diào)用關(guān)系可視出來(lái)。Dapper已有實(shí)現(xiàn)主要在遠(yuǎn)程過(guò)程調(diào)用(RPC)場(chǎng)景,對(duì)應(yīng)用開(kāi)發(fā)者未完全實(shí)現(xiàn)“零侵入”嘲。
2設(shè)計(jì)實(shí)現(xiàn)
2.1方案
消息中間件(MOM)采用發(fā)布/訂閱模式,生產(chǎn)者將消息發(fā)送到主題中,中間件將主題中消息發(fā)送給訂閱者,將Dapper的TRACE,ID、SPAN,ID和PARENT ID在發(fā)布訂閱消息中傳遞,應(yīng)用將ID持久化到日志中,通過(guò)日志則可分析出調(diào)用鏈。
如圖1所示,業(yè)務(wù)流由APPl發(fā)起消息,消息APP2和APP3訂閱處理,APP2處理之后發(fā)布新消息,新消息APP4訂閱處理,一次完整的業(yè)務(wù)流經(jīng)過(guò)APP1、APP2、APP3、APP4和中間件5個(gè)組件,參照Dapper原理過(guò)程如下:
1)APP1業(yè)務(wù)流發(fā)起來(lái),生成一個(gè)Traceid假若為1,Parentid等于自身Moduleid為1,兩個(gè)id攜帶在發(fā)布的消息中,同時(shí)id持久化到日志中;
2)APP2訂閱到消息,首先將接收到消息的Traceid=1、Parentid=1持久化到日志中,消息處理完成后生成新消息,新消息Traceid繼承已處理消息的Traceid為1,Parentid等于自身Moduleid為2;
3)APP4訂閱到消息,將接收到消息的Traceid=1、Parentid=2持久化到日志中;
41 APP3訂閱到消息,將接收到消息的Traceid=1、Parentid=2持久化到日志中。
步驟2中APP2發(fā)布新消息繼承Traceid對(duì)應(yīng)用程序“零侵人”原理在消息處理進(jìn)程/線程上下文未改變。日志文件命名與Moduleid一致,通過(guò)日志文件中的Traceid、Parentid則可以將業(yè)務(wù)流調(diào)用鏈識(shí)別出來(lái)。APP發(fā)送/接收端記錄日志信息,同樣中間件接收,發(fā)送端也記錄日志信息,日志信息加上時(shí)間戳,不僅是調(diào)用鏈,業(yè)務(wù)流完整耗時(shí)、分段耗時(shí)、應(yīng)用耗時(shí)占比、熱點(diǎn)應(yīng)用都可識(shí)別出來(lái),幫助運(yùn)維者管理和決策。
方案實(shí)現(xiàn)存在以下幾個(gè)問(wèn)題需要考慮:
1)Traceid和Moduleid確保系統(tǒng)全局唯一,需要有一個(gè)ID生成策略;
2)調(diào)用鏈跟蹤影響系統(tǒng)正常運(yùn)行,涉及組件眾多,如何動(dòng)態(tài)開(kāi)關(guān)功能;
3)調(diào)用鏈生成大量的日志需要機(jī)器分析,日志規(guī)格化便于機(jī)器分析。
2.2ID生成策略
Traceid代表一次業(yè)務(wù)流,不能出現(xiàn)兩個(gè)一樣的Traceid,使用時(shí)間戳是一個(gè)很好的辦法,Linux時(shí)間戳精確到微妙/納秒,如果在APP端生成Traceid,同一個(gè)時(shí)間精度點(diǎn)上可能小概率出現(xiàn)兩個(gè)APP生成相同的Traceid。中間件為單線程處理,單次處理耗時(shí)小于一個(gè)時(shí)間戳精度不會(huì)發(fā)生,因此在中間件中生成更合理,Traceid規(guī)則如下:
考慮到中間件是多實(shí)例多進(jìn)程,Traceid中加人中間件ID。由于0號(hào)Traceid在系統(tǒng)中中約定為不存在ID號(hào),需要保證生成的Traceid不為0,因此將最后12bit最后一位設(shè)置為1。
Moduleid需要考慮應(yīng)用進(jìn)程在多實(shí)例的情況下也能夠識(shí)別,Moduleid組成格式-。Moduleid采用字符串構(gòu)成,使用Pid來(lái)區(qū)分業(yè)務(wù)進(jìn)程多實(shí)例的情況??紤]到服務(wù)鏈跟蹤需要做到應(yīng)用“零侵入”,新增功能不需要修改代碼,Moduleid不能夠由業(yè)務(wù)來(lái)進(jìn)行設(shè)置,應(yīng)用使用中間件時(shí)注冊(cè)了Moduleid,因此可由中間件直接將Moduleid加入到消息通告中,應(yīng)用無(wú)需感知。
2.3功能開(kāi)關(guān)
服務(wù)鏈跟蹤功能默認(rèn)開(kāi)啟,一個(gè)是影響正常業(yè)務(wù)性能,一個(gè)是產(chǎn)生大量log,兩個(gè)都浪費(fèi)系統(tǒng)資源,因此需要支持動(dòng)態(tài)開(kāi)關(guān)。一次業(yè)務(wù)流涉及的所有應(yīng)用很難提前知曉,發(fā)起應(yīng)用則很容易知道,在業(yè)務(wù)流發(fā)起應(yīng)用打開(kāi)功能更合理的,同時(shí)能支持指定消息主題打開(kāi)。
業(yè)務(wù)流發(fā)起應(yīng)用打開(kāi)功能后,中間件以及所有的下游應(yīng)用如何識(shí)別。發(fā)起應(yīng)用可通過(guò)特定命令告訴中間件該次消息需要使用調(diào)用鏈跟蹤,中間件識(shí)別到則生成一個(gè)新的Traceid,并在消息通告中攜帶上Traceid和Parentid,下流應(yīng)用接收到攜帶ID的消息則認(rèn)為功能開(kāi)啟,這樣鏈?zhǔn)絺鬟f將所有涉及的應(yīng)用功能開(kāi)啟。實(shí)現(xiàn)上將Traceid=O作為功能開(kāi)啟,這也是上小節(jié)為什么將0號(hào)視為不存在的Traceid。業(yè)務(wù)流執(zhí)行完成功能同時(shí)關(guān)閉,因此功能關(guān)閉不需要額外處理。
2.4日志分析
為支持機(jī)器分析日志,日志首先需要支持規(guī)格化,XML/JSON是常用的規(guī)格化方式,嵌入式系統(tǒng)中資源受限使用最簡(jiǎn)單的規(guī)格化方式,在日志將增加標(biāo)簽。單條日志包含的信息如下:其中:
Traceid標(biāo)識(shí)本條日志屬于哪條跟蹤鏈;CMod標(biāo)識(shí)本條日志屬于哪個(gè)應(yīng)用;
LMod標(biāo)識(shí)本條日志Parentid是哪個(gè)應(yīng)用;
Key標(biāo)識(shí)觸發(fā)本次消息的主題;
Act標(biāo)識(shí)觸發(fā)本次消息的增/刪/改行為。
跟蹤日志具有固定的格式,因此可以使用正則表達(dá)式從中分析出所有信息,通過(guò)CMod和LMod找出調(diào)用父子關(guān)系,構(gòu)造出調(diào)用鏈樹(shù)形圖。另外,耗時(shí)可以是日志生成的時(shí)間戳中分析獲取。
3測(cè)試
下圖2展示了系統(tǒng)中一次業(yè)務(wù)流調(diào)用鏈圖,上下流應(yīng)用調(diào)用關(guān)系、消息傳遞的主題Key、業(yè)務(wù)流完整耗時(shí)、各階段耗時(shí)及占比全部可顯示出來(lái),達(dá)到了系統(tǒng)設(shè)計(jì)預(yù)期。
4結(jié)論
本文基于Google Dapper原理實(shí)現(xiàn)了基于消息中間的調(diào)用鏈跟蹤,解決了分布式系統(tǒng)中應(yīng)用之間調(diào)用關(guān)系難于跟蹤定位問(wèn)題,對(duì)于業(yè)務(wù)流時(shí)延性能分析能夠顯著的幫助,優(yōu)化只需要關(guān)注各個(gè)應(yīng)用,完整視圖由機(jī)器來(lái)自動(dòng)化生產(chǎn),節(jié)省人力資源投入。本文實(shí)現(xiàn)還存在下一步優(yōu)化點(diǎn):1)應(yīng)用消息處理更改上下文,如采用異步處理方式;2)分布式節(jié)點(diǎn)中時(shí)間戳存在不一致,耗時(shí)分析增加這部分考慮。