從傳統(tǒng)服務鏈監(jiān)控到端到端流程監(jiān)控技術(shù)實現(xiàn)
今天談下服務鏈監(jiān)控和端到端流程監(jiān)控。對于服務鏈監(jiān)控有開源的類似zipkin,skywalking開源工具可以實現(xiàn)完整的服務鏈監(jiān)控功能,但是采用這些工具的一般都需要在JVM啟動的時候注入探針Jar包,進行訪問攔截。而本方法則是一個自己規(guī)約實現(xiàn)服務鏈監(jiān)控,整體的思路和方法實際和我們常說的服務鏈監(jiān)控是一致的。
服務鏈監(jiān)控實現(xiàn)
SkyWalking監(jiān)控圖
服務鏈監(jiān)控基本概念與場景說明
服務鏈監(jiān)控APM(Application Performance Management)即應用性能管理,屬于IT運維管理(ITOM)范疇。主要是針對企業(yè)關鍵業(yè)務的IT應用性能和用戶體驗的監(jiān)測、優(yōu)化,提高企業(yè)IT應用的可靠性和質(zhì)量,保證用戶得到良好的服務,降低IT總擁有成本(TCO)。
在網(wǎng)絡環(huán)境下,一次獨立的服務請求往往需要涉及到多個服務。由于應用或服務構(gòu)建在不同的軟件模塊上,這些軟件模塊,有可能是由不同的團隊開發(fā)、使用不同的編程語言來實現(xiàn),而且有可能部署在不同的硬件環(huán)境中,橫跨多個不同的數(shù)據(jù)中心。因此,就需要一些可以幫助理解系統(tǒng)行為、用于分析性能問題的工具,以便發(fā)生故障的時候,能夠快速定位和解決問題。
服務鏈監(jiān)控是通常應用于APM,即將實際應用性能和相關服務的調(diào)用關系以服務鏈方式串聯(lián)起來,以便分析和定位實際影響到最終應用性能的關鍵服務,并進行后續(xù)處理。
分布式環(huán)境下的服務鏈監(jiān)控基本模型如下:
圖片
其中,在上圖中有幾個比較重要的概念。
- Span:基本工作單元,一次鏈路調(diào)用創(chuàng)建一個span,通過一個XX位ID標識它,一般是UUID較為方便。當然,Span中還可以有其他的數(shù)據(jù),例如描述信息、時間戳等。
- Trace:類似于樹結(jié)構(gòu)的Span集合,表示一條調(diào)用鏈路,存在唯一標識。
服務鏈監(jiān)控場景說明
如果需要在復雜的網(wǎng)絡環(huán)境上下文中理解分布式系統(tǒng)的行為,就需要監(jiān)控那些橫跨了不同的應用、不同的服務器之間的關聯(lián)動作。在多系統(tǒng)、多模塊、多服務構(gòu)成的架構(gòu)系統(tǒng)中,幾乎每一個前端請求都會形成一個復雜的分布式服務調(diào)用鏈路。
一個服務請求的完整調(diào)用鏈路可能如下圖所示:
圖片
即在前臺功能頁面,點擊提交單據(jù)按鈕的時候,需要調(diào)用業(yè)務內(nèi)部多個服務接口,同時也需要調(diào)用到外部系統(tǒng)提交的服務接口,實現(xiàn)完整的業(yè)務功能邏輯。那就需要對整個服務調(diào)用鏈進行監(jiān)控。
那么,在業(yè)務規(guī)模不斷增大、服務不斷增多以及頻繁變更的情況下,面對復雜的調(diào)用鏈路就帶來一系列問題:
- 如何快速發(fā)現(xiàn)問題?
- 如何判斷故障影響范圍?
- 如何梳理服務依賴以及依賴的合理性?
- 如何分析鏈路性能問題以及實時容量規(guī)劃?
有了服務鏈監(jiān)控,我們能夠做到:
- 提供鏈路追蹤,故障快速定位:可以通過結(jié)合業(yè)務日志快速定位錯誤信息。
- 可視化:各個階段耗時,進行性能分析。
- 依賴優(yōu)化:各個調(diào)用環(huán)節(jié)的可用性、梳理服務依賴關系以及優(yōu)化。
- 數(shù)據(jù)分析,優(yōu)化鏈路:可以得到用戶的行為路徑,匯總分析應用在很多業(yè)務場景。
業(yè)務場景驗證和關鍵技術(shù)實現(xiàn)
在這里,我們舉一個業(yè)務報賬單單據(jù)提交功能來進行說明和驗證。業(yè)務人員在報賬平臺填寫報賬申請單,填寫完成后進行提交,具體涉及到如下操作步驟。
- 進行數(shù)據(jù)完整性校驗(調(diào)用供應商有效性校驗接口,調(diào)用賬戶有效性校驗服務)
- 調(diào)用預算校驗和扣減(調(diào)用預算校驗服務,調(diào)用預算扣減子服務)
- 調(diào)用申請單保存服務,進行申請單保存
- 調(diào)用工作流平臺提供的工作流啟動服務接口進行流程啟動
圖片
服務鏈監(jiān)控的使用規(guī)范
a.在接口服務調(diào)用中增加TRACE_ID信息
需要在接口服務調(diào)用的輸入中增加TRACE_ID字段,作為服務鏈跟蹤使用。
b. TRACE_ID組成說明
一個用于服務鏈監(jiān)控的TRACE_ID的生成,由以下信息所構(gòu)成。
概述:UUID+ SPANID +SPANID+SPANID 組成
說明:UUID為每一個服務調(diào)用鏈,生成一個獨立唯一的UUID值
SPANID:SPANID為01、02順序編碼,服務調(diào)用每進一層增,即增加一層SPANID
圖片
依據(jù)上述規(guī)則,生成的一個參考如下:
TRACE_ID:550e8400-e29b-41d4-a716-446655440000.01.01.02
c. 服務鏈監(jiān)控參考實現(xiàn)偽代碼
根據(jù)前述業(yè)務場景例證的說明,下面以報賬服務的調(diào)用鏈路來說明,如何使用TRACE_ID來進行服務鏈的監(jiān)控。
1. 業(yè)務系統(tǒng)所有的子方法調(diào)用都需要增加TRACE_ID參數(shù)進行傳遞,子方法調(diào)用下一級子方法的時候生成新的TRACE_ID值,即TRACE_ID的定義是遞歸的。
TRACE_ID = TRACE_ID + SPANID
2. SPANID按服務調(diào)用的順序進行兩位編碼,每次步長增加1,諸如01、02、 …. 99
參考下述偽代碼,描述了前述的監(jiān)控實現(xiàn)過程:
public String ApplySubmit()
{
//通過工具類生成UUID
String uuid = utils.generateUUID();
//調(diào)用數(shù)據(jù)檢查服務,通過UUID + SPANID 拼接出每次服務請求的TraceID
Boolean r1 = this.DataValidateSrv(params, uuid + ”.01”);
//調(diào)用預算檢查服務
Boolean r2 = this.BudgetValidateSrv(params, uuid + “.02”);
//調(diào)用單據(jù)保存服務
Boolean r3 = this.BillSaveSrv(params, uuid + “.03”);
//調(diào)用啟動工作流服務
Boolean r4 = this.StartWorkFlow(params, uuid + “.04”);
//結(jié)果返回處理
String result;
return result;
}
對于需要進行跟蹤的下一級服務,也需要依照同樣的原則進行處理:
public String DataValidateSrv(params, TraceID)
{
//調(diào)用供應商檢查服務,通過TRACEID + SPANID 拼接出每次服務請求的TraceID
this.VendorValidateSrv(params, TraceID + ”.01”);
//調(diào)用銀行賬戶檢查服務
this.BankAccountValidateSrv(params, TraceID + “.02”);
//結(jié)果返回處理
String result;
///
return result;
}
d.監(jiān)控日志的記錄
由于在前臺操作觸發(fā)的后臺服務調(diào)用操作中,有可能調(diào)用注冊在集成平臺上的服務,也可以調(diào)用業(yè)務系統(tǒng)內(nèi)部的服務接口,因此,要做到全面的服務鏈監(jiān)控需要對兩部分的日志都進行記錄。
- ESB總線服務:平臺會記錄服務日志,調(diào)用時間消耗;業(yè)務系統(tǒng)也可以同時記錄。
- 業(yè)務系統(tǒng)內(nèi)部服務:集成平臺無法記錄,必須由業(yè)務系統(tǒng)自己記錄。
服務日志需要同時記錄服務調(diào)用時間消耗、服務ID、服務名稱、TRACE_ID、輸入、輸出信息。具體代碼參考如下:
//數(shù)據(jù)檢查服務方法
Void DataValidSrv(params, TRACE_ID);
{
//獲取開始時間
Time StartTime = System.GetCurrentTime();
//獲取入口參數(shù)
Map inputParams = this.method.getParams();
//供應商檢查,實際為UUID.01.01
this.VendorValidSrv(params,TRACE_ID.01);
//銀行賬戶檢查
this.BankValidSrv(params,TRACE_ID.02);
Map outPutParamorData = this.method.getOutPutParams();
Time EndTime = System.GetCurrentTime();
LogSericeData(ServiceID, ‘DataValidSrv’, StartTime , EndTime, inputParams, outPutParams);
}
注:業(yè)務系統(tǒng)也可以采用類似AOP模式進行調(diào)用信息攔截后統(tǒng)一記錄。
服務鏈監(jiān)控的展示
圖片
對于服務鏈監(jiān)控,集成平臺可以根據(jù)記錄的TRACE_ID信息進行關聯(lián),形成服務鏈展示樹,業(yè)務系統(tǒng)提供UUID值,即可以查看到完整的服務調(diào)用鏈,并看到每個服務實例調(diào)用的時間。當然,對于服務鏈監(jiān)控仍然可以參考上篇博文中談到的進行可視化的圖形樹狀結(jié)構(gòu)展示。
當前為了展示方便,主流的服務鏈監(jiān)控基本都是參與表格+樹狀展開的模式進行展示。
端到端流程監(jiān)控
基于接口的跨系統(tǒng)流程概述
在這里的端到端流程監(jiān)控特指跨系統(tǒng)交互業(yè)務流程,即一個完整的端到端流程跨越多個系統(tǒng),多個系統(tǒng)之間通過接口交互來實現(xiàn)協(xié)同。一個完整的端到端流程如下:
圖片
如上圖,一個完整的企業(yè)內(nèi)部自建電商平臺,在完成一個B端客戶的訂單下達,執(zhí)行和交付的時候,需要跨越電商平臺,CRM系統(tǒng),物流平臺,SAP-ERP系統(tǒng)和第三方支付平臺,第三方的物流平臺來共同完成。
那么在下達一個訂單后,當前的流程究竟走到了哪里?是否已經(jīng)完成支付,訂單是否已經(jīng)傳遞到ERP系統(tǒng),訂單是否已經(jīng)安排配送,訂單當前的物流配送是否完成,訂單是否已經(jīng)被客戶簽收等,整合是上面端到端流程里面的關鍵接口交互點。
即:如果一個接口點正常執(zhí)行完,那么說明業(yè)務流已經(jīng)走到下個階段。
而對于類似上圖的跨多個系統(tǒng)的端到端流程,我們往往希望跟蹤一個訂單當前執(zhí)行到哪個階段,具體什么狀態(tài),那么核心的關鍵字就是訂單編號,可以看到后續(xù)的支付,物流,配送,訂單執(zhí)行等相關接口,接口的輸入信息中都會有訂單編號這個關鍵字。
跨系統(tǒng)交互流程建模
可視化接口交互流程設計
從前面分析可以看到,可以通過接口交互分析來倒推流程。因此我們可以對接口交互流程進行可視化設計和建模。同時對所有的接入注冊到ESB服務總線進行管理。
由于接口服務都通過ESB服務總線進行封裝代理后接入,因此理論上說從實際業(yè)務服務調(diào)用實例數(shù)據(jù)和日志中是可以反推出來端到端的業(yè)務流程的,也就是可以通過服務實例和服務鏈的監(jiān)控來間接的監(jiān)控跨系統(tǒng)的業(yè)務流轉(zhuǎn)是否正常。
簡單來說,比如一個采購訂單,基于一個采購訂單號,我們實際上可以通過服務監(jiān)控數(shù)據(jù)來分析到該訂單是否已經(jīng)從采購系統(tǒng)導入到ERP,是否已經(jīng)進行了報賬申請,是否已經(jīng)進行了付款等,實際上這些信息從服務實例日志中都可以提取出來。
要完成這件事情,實際上有兩個關鍵點要做,即首先要對服務鏈本身進行進行服務鏈流程建模,其次是能夠?qū)Σ杉娜罩镜妮斎胼敵鲋心軌蜃ト〕鼋Y(jié)構(gòu)化的關鍵業(yè)務字段信息。只要做到這兩點,我們就很容易實現(xiàn)可視化的跨系統(tǒng)服務鏈監(jiān)控功能。
在前面我們做ESB服務設計器的時候,已經(jīng)已經(jīng)剝離了原流程引擎中進行服務編排或可視化流程建模的能力。實際上這里的設計本身也就是一個多個服務編排設計的過程,將多個服務編排設計到一起。注意在這個過程中還需要允許有分支,也允許并行。服務鏈監(jiān)控最終形成的也是一個完整的服務鏈監(jiān)控樹。只是這個監(jiān)控樹的形成是通過可視化的服務組合編排工具來實現(xiàn)的而已。
針對不同的跨系統(tǒng)業(yè)務監(jiān)控,都需要針對不同場景設計不同的服務監(jiān)控模型。
比如現(xiàn)在設計一個采購訂單服務鏈監(jiān)控模型,我們可以對該模型進行簡化,具體如下通過建模工具形成如下模型樹。合同導入服務-》采購訂單導入服務-》采購接收服務-》報賬申請服務-》應付發(fā)票導入服務-》付款服務。
我們完全可以采用流程設計和建模工具來完成上圖的流程模型,當然如果采用類似支持BPMN標準的流程建模工具還可以進一步完成跨系統(tǒng)交互流程圖。
在這個跨系統(tǒng)交互流程圖中,銜接各個業(yè)務系統(tǒng)的仍然是相互之間的接口和服務,我們?nèi)匀皇前凑找粋€核心單據(jù)為基本元素來進行設計,比如項目編號,合同編號,采購訂單編號等。以這個編號來完成整個跨系統(tǒng)端到端流程的分析。
在建模的過程中,兩個系統(tǒng)間的連接線就是關鍵的接口服務,但是由于不是直接的服務間的連接,因此仍然需要建立服務之間的關聯(lián)性。比如我們整體跨系統(tǒng)監(jiān)控都是以采購訂單號來進行跟蹤的話,我們就需要定義采購訂單這個元素在每一個接口服務中對應的XML-Element的位置,以確保這些服務之間本身能夠關聯(lián)起來。
整體我們看到實現(xiàn)的思路和服務鏈監(jiān)控基本相同。
仍然是先根據(jù)業(yè)務關鍵字查詢功能,精確查詢出相關的服務實例數(shù)據(jù)。然后將服務實例數(shù)據(jù)映射到流程圖上面,形成流程圖實例。對于已經(jīng)成功運行的服務標注為綠色,對于接口調(diào)用失敗的服務標注為紅色,對于還沒有執(zhí)行到的服務標注為灰色。
同時更加有意義的事情是,我們完全可以來動畫效果模擬這個跨系統(tǒng)接口交互流程。即能夠動態(tài)的看到各個接口被觸發(fā)和調(diào)用的前后順序。同時看到前后接口觸發(fā)的大致時間間隔信息。通過這種實現(xiàn)能夠很方便我們實現(xiàn)圍繞核心業(yè)務對象的端到端流程監(jiān)控能力。
當然這是一種變通的端到端流程監(jiān)控實現(xiàn)思路,核心是先進行流程建模,然后再通過業(yè)務關鍵字檢索功能動態(tài)搜索匹配的服務日志調(diào)用數(shù)據(jù),再對流程圖進行實例化解析。由于采用了Solr全文檢索能力,這個比我們完全自頂向下的來進行端到端流程監(jiān)控實現(xiàn)更加高效。
業(yè)務日志采集和監(jiān)控查詢
圖片
在前面有篇文章我們專門談到過基于Solr進行業(yè)務關鍵字查詢和報文日志全文檢索。而這個功能本身剛好用到服務鏈監(jiān)控里面。即我們不再需要對服務運行報文數(shù)據(jù)全部進行結(jié)構(gòu)化數(shù)據(jù),而只需要對這些數(shù)據(jù)建立元數(shù)據(jù)索引信息,有了索引后Solr基本就可以快速的檢索和定位到具體的服務。
對于當前的服務日志,我們已經(jīng)完成了將Blob結(jié)構(gòu)的數(shù)據(jù)準實時的采集并提取索引信息,進入到Solr庫,實現(xiàn)了基于業(yè)務關鍵字的服務實例查詢能力,而原來我們只能基于服務實例號進行服務日志的查詢。
基于Solr查詢速度相當快,基本都是10多毫秒就能快速完成服務日志的檢索能力。在Solr實現(xiàn)了索引數(shù)據(jù)的創(chuàng)建,基于業(yè)務關鍵字的查詢能力后,接下來分析如何和服務鏈監(jiān)控進行整合。
舉例來說,對于采購訂單服務鏈監(jiān)控,進入該功能后我們直接輸入采購訂單號,然后基于訂單號我們做如下事情。
- 首先找到采購訂單服務鏈監(jiān)控流程模板,然后基于流程模板知道涉及哪些服務。
- 找到流程模板中維護的Xpath檢索項
- 基于Xpath檢索項找的信息,拼裝Solr查詢關鍵字,然后進行Solr查找到對應服務日志記錄。
- 將服務日志記錄提取出來對應到流程實例具體的活動節(jié)點上面。
- 完成流程實例圖的顯示。
當我們點擊線條的時候可以查看到詳細的每筆接口服務調(diào)用日志信息。具體參考圖如下:
圖片
以上即是一個完整的基于Solr和ESB總線結(jié)合來實現(xiàn)端到端流程監(jiān)控的一個技術(shù)實現(xiàn)思路。該功能已經(jīng)在我們自研的ESB服務總線和IPaaS管控治理平臺得到實現(xiàn),并得到很好的展現(xiàn)效果。