金越成
(上海金融期貨信息技術(shù),上海 200122)
單體架構(gòu)轉(zhuǎn)向微服務(wù)架構(gòu)不只是部署的變化,其會從業(yè)務(wù)分析、業(yè)務(wù)域劃分、服務(wù)開發(fā)、上線部署、線上運維等多方面都帶來挑戰(zhàn)。微服務(wù)架構(gòu)分布式軟件系統(tǒng)具有以下特點:節(jié)點規(guī)模龐大、系統(tǒng)結(jié)構(gòu)與組件依賴關(guān)系復(fù)雜、規(guī)模不斷增長[1]。
尤其是在線上運維中,出現(xiàn)異常報警的時候如何快速定位故障問題,單體架構(gòu)下直接查看日志分析就可以滿足,但是在微服務(wù)架構(gòu)中,一項業(yè)務(wù)通常需要經(jīng)過多個服務(wù)鏈條,如果依然沿用查看日志分析的方法,就需要登錄到不同的機(jī)器去查看日志,這無疑增加了工作難度,且如果有日志中心,看到的日志是多段的無法排序的。這樣就導(dǎo)致微服務(wù)架構(gòu)下出現(xiàn)了比較典型的兩個問題:
(1)一個請求經(jīng)過服務(wù)鏈條上的多項服務(wù)時,其中出現(xiàn)了一個調(diào)用失敗的問題,且只能判斷有異常,具體的異常是哪個服務(wù)引起的就需要進(jìn)入每一個服務(wù)里面看日志,這樣的排障效率是非常低的;
(2)一個請求經(jīng)過一系列服務(wù)之后最終返回錯誤或者超時,但各服務(wù)都正常運行,且無法判斷是哪個服務(wù)響應(yīng)時間過長,因此需要查看每個服務(wù)的日志文件,但無法確定服務(wù)調(diào)用的時間和時長[2]。
谷歌在2010年4月發(fā)表了一篇論文Dapper, a Large-Scale Distributed Systems Tracing Infrastructure,介紹了分布式追蹤的幾個概念:
(1)追蹤Trace就是由分布的微服務(wù)協(xié)作所支撐的一個事務(wù),一個追蹤包含為該事務(wù)提供服務(wù)的各個服務(wù)請求;
(2)跨度Span是事務(wù)中的一個工作流,一個Span包含了時間戳、日志和標(biāo)簽信息,而Span之間包含父子關(guān)系或者主從關(guān)系;
(3)跨度上下文Span Context是支撐分布式追蹤的關(guān)鍵,它可以在調(diào)用的服務(wù)之間傳遞,上下文的內(nèi)容包括諸如從一個服務(wù)傳遞到另一個服務(wù)的時間、追蹤的ID,還有其他需要從上游服務(wù)傳遞到下游服務(wù)的信息[3]。
(4)行業(yè)標(biāo)準(zhǔn),OpenTracing是個標(biāo)準(zhǔn)化組織,提高了不同廠商間的互操作性,只要遵循OpenTracing標(biāo)準(zhǔn),企業(yè)可以根據(jù)需要替換具體的追蹤產(chǎn)品。
(5)主流的分布式追蹤組件,zipkin、skywalking、jaeger都符合這個標(biāo)準(zhǔn)且具有很好的兼容性。
但這些產(chǎn)品的引入都對業(yè)務(wù)系統(tǒng)有侵入,需要應(yīng)用重新發(fā)版本,而且無法滿足所有需求,需要進(jìn)行二次開發(fā)。
設(shè)計目標(biāo):當(dāng)出現(xiàn)問題的時候能夠快速地定位;對業(yè)務(wù)透明,業(yè)務(wù)不需要強依賴;可擴(kuò)展,將來的運維需求可以放在里面。
場景及存在的問題如下。
(1)場景1:可以迅速發(fā)現(xiàn)日志異常并定位發(fā)生點。
當(dāng)前問題:目前有HTTP層的應(yīng)答碼規(guī)范、微服務(wù)框架層有明確的錯誤碼定義,但網(wǎng)關(guān)的錯誤信息不夠詳細(xì)。
(2)場景2:將調(diào)用鏈信息和日志信息結(jié)合起來,迅速還原異常發(fā)生時的分布式場景。
當(dāng)前問題:微服務(wù)框架目前在Log記錄方面內(nèi)容比較詳細(xì),會自動記錄日志,但是在Trace方面存在短板。微服務(wù)框架埋點生成的trace日志,在排序方面難以滿足分布式需求(跨組件日志穿插),在深度方面不夠深入,存在引入的第三方組件沒有支持的問題。
(3)場景3:可以迅速發(fā)現(xiàn)并定位性能問題。
當(dāng)前問題:目前最外層Controller層打印了耗時信息,但是內(nèi)部的調(diào)用關(guān)系(模塊間調(diào)用、中間件調(diào)用)和耗時信息缺乏,導(dǎo)致只能定位接口級別的性能問題,定位粒度較粗。保障有工具進(jìn)行了一些Metric的監(jiān)控(例如Redis),但基本是以分鐘為粒度去監(jiān)控,定位能力有限。
(4)場景4:希望能夠看到完整的線上依賴關(guān)系視圖。
當(dāng)前問題:目前的日志能夠體現(xiàn)依賴關(guān)系,但是存在如下問題,即只有部分系統(tǒng)升級到了新的日志版本,依賴關(guān)系不全,依賴關(guān)系的粒度比較粗(服務(wù)→URL,服務(wù)->URL),無法形成端到端的URL級別的依賴關(guān)系(URL->URL)[4]。
(5)場景:對日志、追蹤等的完善版本盡快生效。
當(dāng)前問題:業(yè)務(wù)系統(tǒng)目前對于日志等組件是強依賴關(guān)系(依賴于微服務(wù)框架的整體升級),由于業(yè)務(wù)系統(tǒng)本身的升級頻率不一、測試成本高等問題,很難推動業(yè)務(wù)系統(tǒng)進(jìn)行微服務(wù)框架的整體升級,治理需求在線上系統(tǒng)的收斂速度慢、生效周期長。
(6)場景:避免應(yīng)用的版本對日志等治理組件強依賴。
當(dāng)前問題:目前由于是這種強依賴關(guān)系,導(dǎo)致應(yīng)用升級日志組件需要整體升級微服務(wù)框架。
(7)場景:架構(gòu)治理組件不能引起太多性能降低。
當(dāng)前問題;目前性能影響不大。
(8)場景:使用標(biāo)準(zhǔn)的模型,避免在設(shè)計上擠牙膏,定位到容器pod。
當(dāng)前問題:目前根據(jù)可見需求自己定義了一套trace體系,但是從演進(jìn)過程來看較SkyWalking提煉過的模型差距較大[5]。
(1)對業(yè)務(wù)完全無侵入引入Agent的方式。官方的Skywalking Agent需要修改pom添加對應(yīng)的包依賴及修改日志配置,應(yīng)用需要重新發(fā)版本。
(2)支持日志模型擴(kuò)展,通過日志中心能夠看出日志塊的調(diào)用順序。
利用Java Agent實現(xiàn)業(yè)務(wù)無侵入的目標(biāo),JVM1.5以后支持在主程序前運行Agent和主程序運行后運行Agent兩種模式。
(1)啟動時調(diào)用Instrumentation的loadClass AndCallPremain方法,在這個方法中會調(diào)用JavaAgent里MANIFEST.MF指定的Premain-Class類的premain方法。
(2)運行時修改主要是通過JVM的attach機(jī)制來請求目標(biāo)JVM加載對應(yīng)的Agent,調(diào)用InstrumentationImpl的loadClassAndCallAgentmain方法,在這個方法中會調(diào)用JavaAgent中MANIFEST.MF指定的Agentmain-Class類的Agentmain方法。
Skywalking是Apache孵化的產(chǎn)品,是專門為微服務(wù)架構(gòu)和云原生架構(gòu)系統(tǒng)而設(shè)計并且支持分布式鏈路追蹤的APM系統(tǒng)。其通過加載非侵入探針的方式收集應(yīng)用中的調(diào)用鏈路信息,并對采集的調(diào)用鏈路信息進(jìn)行分析,生成應(yīng)用間關(guān)系、服務(wù)間關(guān)系以及服務(wù)指標(biāo)。其支持多種語言,包括Java,.Net,PHP,Python,Node.js, C++。使用此系統(tǒng)需要在代碼的pom中顯示引入的依賴,然后在日志配置文件中使用相應(yīng)的插件,最大的問題是需要應(yīng)用升級發(fā)布新的版本。
自適應(yīng)微服務(wù)追蹤插件的核心理念是業(yè)務(wù)無侵入,基于字節(jié)碼增強技術(shù)實現(xiàn)無侵入Agent服務(wù)治理能力,業(yè)務(wù)無需修改代碼即可實現(xiàn)服務(wù)追蹤、運維等需求。自定義Agent作為JVM層的切面,在進(jìn)行跨組件調(diào)用的時候會記錄事件,在日志中打印調(diào)用鏈信息,然后異步上報到管理端。自定義Agent作為Skywalking Agent和業(yè)務(wù)代碼的橋梁,需要將應(yīng)用中顯示的依賴放在自定義Agent中,日志配置插件也不用顯示修改,在運行時進(jìn)行動態(tài)替換(圖1)。
圖1 Agent 示例
插件有以下核心優(yōu)勢:
(1)代碼無侵入、業(yè)務(wù)無感知,即業(yè)務(wù)無需對程序代碼做任何修改,只需在應(yīng)用啟動項添加Agent參數(shù)即可;
(2)運維需求下移,即運維上請求進(jìn)出標(biāo)志位,日志分層需求下移到基礎(chǔ)設(shè)施層;
(3)模塊化設(shè)計,使業(yè)務(wù)可按需加載、卸載功能模塊及升級。
(4)日志模型擴(kuò)展,目的是實現(xiàn)通過日志中心查看日志能夠看出調(diào)用順序。
2.3.1 Trace 擴(kuò)展模型在日志中的應(yīng)用
TraceID:TraceID是一次請求唯一的標(biāo)識,被應(yīng)用日志和skywalking日志共用。
sqn:擴(kuò)展字段,用來標(biāo)識分布式環(huán)境下調(diào)用層級和調(diào)用順序。規(guī)則是從1開始順序遞增,每增減一個點號代表多一層調(diào)用,如1.1 是1.1.1的parent,2表示在1后面執(zhí)行的(圖2)。
圖2 模型擴(kuò)展
在傳統(tǒng)環(huán)境中,每臺虛機(jī)都部署一個Agent客戶端,在應(yīng)用的啟動腳本中添加引用Agent的腳本。對開發(fā)測試人員無感知,運維人員線上運維變更只需一鍵就可開啟所有應(yīng)用的追蹤。在容器環(huán)境中,Agent通過hostpath掛卷到node節(jié)點上,云平臺屏蔽了掛卷及啟動加載的細(xì)節(jié),對開發(fā)應(yīng)用透明。
實施步驟:
(1)啟動腳本修改,-javaagent:/java_agent/leo_agent/myAgent.jar -javaagent:/java_agent/skywalking_agent/skywalking-agent.jar=agent.service_name=serviceName;
(2)配置文件修改,增加默認(rèn)skywalking collector的地址sky.coll.com:8080;
(3)選擇c o l l e c t o r 的存儲模式e s 7,配置elasticsearch的地址、用戶名、密碼;
(4)配置域名,在客戶端服務(wù)器上/etc/hosts配置域名sky.coll.com對應(yīng)的IP。
傳統(tǒng)金融行業(yè)的特點是對安全性的要求特別高,這就導(dǎo)致了業(yè)務(wù)系統(tǒng)對升級基礎(chǔ)框架特別謹(jǐn)慎。由于應(yīng)用使用各個框架版本不同,甚至跨度很大,通過在基礎(chǔ)框架中的埋點打印運維日志的功能實施難度太大,難以快速地在線上環(huán)境推動調(diào)用鏈跟蹤落地。使用這種自適應(yīng)微服務(wù)追蹤技術(shù)可以解決以上問題,同時還可以提升線上環(huán)境排障效率,快速定位錯誤。