序言
時(shí)間回到2008年,還在上海交通大學(xué)上學(xué)的張旭豪、康嘉等人在上海創(chuàng)辦了餓了么,從校園外賣場(chǎng)景出發(fā),餓了么一步一步發(fā)展壯大,成為外賣行業(yè)的領(lǐng)頭羊。2017年8月餓了么并購百度外賣,強(qiáng)強(qiáng)合并,繼續(xù)開疆?dāng)U土。2018年餓了么加入阿里巴巴大家庭,與口碑融合成立阿里巴巴本地生活公司。“愛什么,來什么”,是餓了么對(duì)用戶不變的承諾。
餓了么的技術(shù)也伴隨著業(yè)務(wù)的飛速增長也不斷突飛猛進(jìn)。據(jù)公開報(bào)道,2014年5月的日訂單量只有10萬,但短短幾個(gè)月之后就沖到了日訂單百萬,到當(dāng)今日訂單上千萬單。在短短幾年的技術(shù)發(fā)展歷程上,餓了么的技術(shù)體系、穩(wěn)定性建設(shè)、技術(shù)文化建設(shè)等都有長足的發(fā)展。各位可查看往期文章一探其中發(fā)展歷程,在此不再贅述:
而可觀測(cè)性作為技術(shù)體系的核心環(huán)節(jié)之一,也跟隨餓了么技術(shù)的飛速發(fā)展,不斷自我革新,從“全鏈路可觀測(cè)性ETrace”擴(kuò)展到“多活下的可觀測(cè)性體系ETrace”,發(fā)展成目前“一站式可觀測(cè)性平臺(tái)EMonitor”。
EMonitor經(jīng)過5年的多次迭代,現(xiàn)在已經(jīng)建成了集指標(biāo)數(shù)據(jù)、鏈路追蹤、可視化面板、報(bào)警與分析等多個(gè)可觀測(cè)性領(lǐng)域的平臺(tái)化產(chǎn)品。EMonitor每日處理約1200T的原始可觀測(cè)性數(shù)據(jù),覆蓋餓了么絕大多數(shù)中間件,可觀測(cè)超5萬臺(tái)機(jī)器實(shí)例,可觀測(cè)性數(shù)據(jù)時(shí)延在10秒左右。面向餓了么上千研發(fā)人員,EMonitor提供精準(zhǔn)的報(bào)警服務(wù)和多樣化的觸達(dá)手段,同時(shí)運(yùn)行約2萬的報(bào)警規(guī)則。本文就細(xì)數(shù)餓了么可觀測(cè)性的建設(shè)歷程,回顧下“餓了么可觀測(cè)性建設(shè)的那些年”。
1.0:混沌初開,萬物興起
翻看代碼提交記錄,ETrace項(xiàng)目的第一次提交在2015年10月24日。而2015年,正是餓了么發(fā)展的第七個(gè)年頭,也是餓了么業(yè)務(wù)、技術(shù)、人員開始蓬勃發(fā)展的年頭。彼時(shí),餓了么的可觀測(cè)性系統(tǒng)依賴Zabbix、Statsd、Grafana等傳統(tǒng)的“輕量級(jí)”系統(tǒng)。而“全鏈路可觀測(cè)性”正是當(dāng)時(shí)的微服務(wù)化技術(shù)改造、后端服務(wù)Java化等技術(shù)發(fā)展趨勢(shì)下的必行之勢(shì)。
我們可觀測(cè)性團(tuán)隊(duì),在調(diào)研業(yè)界主流的全鏈路可觀測(cè)性產(chǎn)品--包括著名的開源全鏈路可觀測(cè)性產(chǎn)品“CAT”后,吸取眾家之所長,在兩個(gè)多月的爆肝開發(fā)后,推出了初代ETrace。我們提供的Java版本ETrace-Agent隨著新版的餓了么SOA框架“Pylon”在餓了么研發(fā)團(tuán)隊(duì)中的推廣和普及開來。ETrace-Agent能自動(dòng)收集應(yīng)用的SOA調(diào)用信息、API調(diào)用信息、慢請(qǐng)求、慢SQL、異常信息、機(jī)器信息、依賴信息等。下圖為1.0版本的ETrace頁面截圖。
在經(jīng)歷了半年的爆肝開發(fā)和各中間件兄弟團(tuán)隊(duì)的鼎力支持,我們又開發(fā)了Python版本的Agent,更能適應(yīng)餓了么當(dāng)時(shí)各語言百花齊放的技術(shù)體系。并且,通過和餓了么DAL組件、緩存組件、消息組件的密切配合與埋點(diǎn),用戶的應(yīng)用增加了多層次的訪問信息,鏈路更加完整,故障排查過程更加清晰。
整體架構(gòu)體系
ETrace整體架構(gòu)如下圖。通過SDK集成在用戶應(yīng)用中的Agent定期將Trace數(shù)據(jù)經(jīng)Thrift協(xié)議發(fā)送到Collector(Agent本地不落日志),Collector經(jīng)初步過濾后將數(shù)據(jù)打包壓縮發(fā)往Kafka。Kafka下游的Consumer消費(fèi)這些Trace數(shù)據(jù),一方面將數(shù)據(jù)寫入Hbase+HDFS,一方面根據(jù)與各中間件約定好的埋點(diǎn)規(guī)則,將鏈路數(shù)據(jù)計(jì)算成指標(biāo)存儲(chǔ)到時(shí)間序列數(shù)據(jù)庫-- LinDB中。在用戶端,Console服務(wù)提供UI及查詢指標(biāo)與鏈路數(shù)據(jù)的API,供用戶使用。
全鏈路可觀測(cè)性的實(shí)現(xiàn)
所謂全鏈路可觀測(cè)性,即每次業(yè)務(wù)請(qǐng)求中都有唯一的能夠標(biāo)記這次業(yè)務(wù)完整的調(diào)用鏈路,我們稱這個(gè)ID為RequestId。而每次鏈路上的調(diào)用關(guān)系,類似于樹形結(jié)構(gòu),我們將每個(gè)樹節(jié)點(diǎn)上用唯一的RpcId標(biāo)記。
如圖,在入口應(yīng)用App1上會(huì)新建一個(gè)隨機(jī)RequestId(一個(gè)類似UUID的32位字符串,再加上生成時(shí)的時(shí)間戳)。因它為根節(jié)點(diǎn),故RpcId為“1”。在后續(xù)的RPC調(diào)用中,RequestId通過SOA框架的Context傳遞到下一節(jié)點(diǎn)中,且下一節(jié)點(diǎn)的層級(jí)加1,變?yōu)樾稳纭?.1”、“1.2”。如此反復(fù),同一個(gè)RequestId的調(diào)用鏈就通過RpcId還原成一個(gè)調(diào)用樹。
也可以看到,“全鏈路可觀測(cè)性的實(shí)現(xiàn)”不僅依賴與ETrace系統(tǒng)自身的實(shí)現(xiàn),更依托與公司整體中間件層面的支持。如在請(qǐng)求入口的Gateway層,能對(duì)每個(gè)請(qǐng)求生成“自動(dòng)”新的RequestId(或根據(jù)請(qǐng)求中特定的Header信息,復(fù)用RequestId與RpcId);RPC框架、Http框架、Dal層、Queue層等都要支持在Context中傳遞RequestId與RpcId。
ETrace Api示例
在Java或Python中提供鏈路埋點(diǎn)的API:
/*記錄一個(gè)調(diào)用鏈路/Transaction trasaction = Trace.newTransaction(String type, String name);// business codestransaction.complete();/*記錄調(diào)用中的一個(gè)事件/Trace.logEvent(String type, String name, Map<String,String> tags, String status, String data)/*記錄調(diào)用中的一個(gè)異常/Trace.logError(String msg, Exception e)
Consumer的設(shè)計(jì)細(xì)節(jié)
Consumer組件的核心任務(wù)就是將鏈路數(shù)據(jù)寫入存儲(chǔ)。主要思路是以RequestId+RpcId作為主鍵,對(duì)應(yīng)的Data數(shù)據(jù)寫入存儲(chǔ)的Payload。再考慮到可觀測(cè)性場(chǎng)景是寫多讀少,并且多為文本類型的Data數(shù)據(jù)可批量壓縮打包存儲(chǔ),因此我們?cè)O(shè)計(jì)了基于HDFS+Hbase的兩層索引機(jī)制。
如圖,Consumer將Collector已壓縮好的Trace數(shù)據(jù)先寫入HDFS,并記錄寫入的文件Path與寫入的Offset,第二步將這些“索引信息”再寫入Hbase。特別的,構(gòu)建Hbase的Rowkey時(shí),基于ReqeustId的Hashcode和Hbase Table的Region數(shù)量配置,來生成兩個(gè)Byte長度的ShardId字段作為Rowkey前綴,避免了某些固定RequestId格式可能造成的寫入熱點(diǎn)問題。(因RequestId在各調(diào)用源頭生成,如應(yīng)用自身、Nginx、餓了么網(wǎng)關(guān)層等。可能某應(yīng)用錯(cuò)誤設(shè)置成以其AppId為前綴RequestId,若沒有ShardId來打散,則它所有RequestId都將落到同一個(gè)Hbase Region Server上。)
在查詢時(shí),根據(jù)RequestId + RpcId作為查詢條件,依次去Hbase、HDFS查詢?cè)紨?shù)據(jù),便能找到某次具體的調(diào)用鏈路數(shù)據(jù)。但有的需求場(chǎng)景是,只知道源頭的RequestId需要查看整條鏈路的信息,希望只排查鏈路中狀態(tài)異常的或某些指定RPC調(diào)用的數(shù)據(jù)。因此,我們?cè)贖Bbase的Column Value上還額外寫了RPCInfo的信息,來記錄單次調(diào)用的簡要信息。如:調(diào)用狀態(tài)、耗時(shí)、上下游應(yīng)用名等。
此外,餓了么的場(chǎng)景下,研發(fā)團(tuán)隊(duì)多以訂單號(hào)、運(yùn)單號(hào)作為排障的輸入,因此我們和業(yè)務(wù)相關(guān)團(tuán)隊(duì)約定特殊的埋點(diǎn)規(guī)則--在Transaction上記錄一個(gè)特殊的"orderId={實(shí)際訂單號(hào)}"的Tag--便會(huì)在Hbase中新寫一條“訂單表”的記錄。該表的設(shè)計(jì)也不復(fù)雜,Rowkey由ShardId與訂單號(hào)組成,Columne Value部分由對(duì)應(yīng)的RequestId+RpcId及訂單基本信息(類似上文的RPCInfo)三部分組成。
如此,從業(yè)務(wù)鏈路到全鏈路信息到詳細(xì)單個(gè)鏈路,形成了一個(gè)完整的全鏈路排查體系。
Consumer組件的另一個(gè)任務(wù)則是將鏈路數(shù)據(jù)計(jì)算成指標(biāo)。實(shí)現(xiàn)方式是在寫入鏈路數(shù)據(jù)的同時(shí),在內(nèi)存中將Transaction、Event等數(shù)據(jù)按照既定的計(jì)算邏輯,計(jì)算成SOA、DAL、Queue等中間件的指標(biāo),內(nèi)存稍加聚合后再寫入時(shí)序數(shù)據(jù)庫LinDB。
指標(biāo)存儲(chǔ):LinDB 1.0
應(yīng)用指標(biāo)的存儲(chǔ)是一個(gè)典型的時(shí)間序列數(shù)據(jù)庫的使用場(chǎng)景。根據(jù)我們以前的經(jīng)驗(yàn),市面上主流的時(shí)間序列數(shù)據(jù)庫-- OpenTSDB、InfluxDB、Graphite--在擴(kuò)展能力、集群化、讀寫效率等方面各有缺憾,所以我們選型使用RocksDB作為底層存儲(chǔ)引擎,借鑒Kafka的集群模式,開發(fā)了餓了么的時(shí)間序列數(shù)據(jù)庫--LinDB。
指標(biāo)采用類似Prometheus的“指標(biāo)名+鍵值對(duì)的Tags”的數(shù)據(jù)模型,每個(gè)指標(biāo)只有一個(gè)支持Long或Double的Field。某個(gè)典型的指標(biāo)如:
COUNTER: eleme_makeorder{city="shanghai",channel="app",status="success"} 45
我們主要做了一些設(shè)計(jì)實(shí)現(xiàn):
這套存儲(chǔ)方案在初期很好的支持了ETrace的指標(biāo)存儲(chǔ)需求,為ETrace大規(guī)模接入與可觀測(cè)性數(shù)據(jù)的時(shí)效性提供了堅(jiān)固的保障。有了ETrace,餓了么的技術(shù)人終于能從全鏈路的角度去排查問題、治理服務(wù),為之后的技術(shù)升級(jí)、架構(gòu)演進(jìn),提供了可觀測(cè)性層面的支持。
其中架構(gòu)的幾點(diǎn)說明
1. 是否保證所有可觀測(cè)性數(shù)據(jù)的可靠性?
不,我們承諾的是“盡可能不丟”,不保證100%的可靠性。基于這個(gè)前提,為我們?cè)O(shè)計(jì)架構(gòu)時(shí)提供了諸多便利。如,Agent與Collector若連接失敗,若干次重試后便丟棄數(shù)據(jù),直到Collector恢復(fù)可用;Kafka上下游的生產(chǎn)和消費(fèi)也不必Ack,避免影響處理效率。
2. 為什么在SDK中的Agent將數(shù)據(jù)發(fā)給Collector,而不是直接發(fā)送到Kafka?
3. SDK中的Agent如何控制對(duì)業(yè)務(wù)應(yīng)用的影響?
4. 為什么選擇侵入性的Agent?
選擇寄生在業(yè)務(wù)應(yīng)用中的SDK模式,在當(dāng)時(shí)看來更利于ETrace的普及與升級(jí)。而從現(xiàn)在的眼光看來,非侵入式的Agent對(duì)用戶的集成更加便利,并且可以通過Kubernates中SideCar的方式對(duì)用戶透明部署與升級(jí)。
5. 如何實(shí)現(xiàn)“盡量不丟數(shù)據(jù)”?
6. 可觀測(cè)性數(shù)據(jù)如何實(shí)現(xiàn)多語言支持?
Agent與Collector之間選擇Thrift RPC框架,并定制整個(gè)序列化方式。Java/Python/Go/PHP的Agent依數(shù)據(jù)規(guī)范開發(fā)即可。
2.0:異地多活,大勢(shì)初成
2016年底,餓了么為了迎接業(yè)務(wù)快速增長帶來的調(diào)整,開始推進(jìn)“異地多活”項(xiàng)目。新的多數(shù)據(jù)中心架構(gòu)對(duì)既有的可觀測(cè)性架構(gòu)也帶來了調(diào)整,ETrace亦經(jīng)過了一年的開發(fā)演進(jìn),升級(jí)到多數(shù)據(jù)中心的新架構(gòu)、拆分出實(shí)時(shí)計(jì)算模塊、增加報(bào)警功能等,進(jìn)入ETrace2.0時(shí)代。
異地多活的挑戰(zhàn)
隨著餓了么的異地多活的技術(shù)改造方案確定,對(duì)可觀測(cè)性平臺(tái)提出了新的挑戰(zhàn):如何設(shè)計(jì)多活架構(gòu)下的可觀測(cè)性系統(tǒng)?以及如何聚合多數(shù)據(jù)中心的可觀測(cè)性數(shù)據(jù)?
經(jīng)過一年多的推廣與接入,ETrace已覆蓋了餓了么絕大多數(shù)各語言的應(yīng)用,每日處理數(shù)據(jù)量已達(dá)到了數(shù)十T以上。在此數(shù)據(jù)規(guī)模下,決不可能將數(shù)據(jù)拉回到某個(gè)中心機(jī)房處理。因此“異地多活”架構(gòu)下的可觀測(cè)性設(shè)計(jì)的原則是:各機(jī)房處理各自的可觀測(cè)性數(shù)據(jù)。
我們開發(fā)一個(gè)Gateway模塊來代理與聚合各數(shù)據(jù)中心的返回結(jié)果,它會(huì)感知各機(jī)房間內(nèi)Console服務(wù)。圖中它處于某個(gè)中央的云上區(qū)域,實(shí)際上它可以部署在各機(jī)房中,通過域名的映射機(jī)制來做切換。
如此部署的架構(gòu)下,各機(jī)房中的應(yīng)用由與機(jī)房相綁定的環(huán)境變量控制將可觀測(cè)性數(shù)據(jù)發(fā)送到該機(jī)房內(nèi)的ETrace集群,收集、計(jì)算、存儲(chǔ)等過程都在同一機(jī)房內(nèi)完成。用戶通過前端Portal來訪問各機(jī)房內(nèi)的數(shù)據(jù),使用體驗(yàn)和之前類似。
即使考慮極端情況下--某機(jī)房完全不可用(如斷網(wǎng)),“異地多活”架構(gòu)可將業(yè)務(wù)流量切換到存活的機(jī)房中,讓業(yè)務(wù)繼續(xù)運(yùn)轉(zhuǎn)。而可觀測(cè)性上,通過將Portal域名與Gateway域名切換到存活的機(jī)房中,ETrace便能繼續(xù)工作(雖然會(huì)缺失故障機(jī)房的數(shù)據(jù))。在機(jī)房網(wǎng)絡(luò)恢復(fù)后,故障機(jī)房內(nèi)的可觀測(cè)性數(shù)據(jù)也能自動(dòng)恢復(fù)(因?yàn)樵摍C(jī)房內(nèi)的可觀測(cè)性數(shù)據(jù)處理流程在斷網(wǎng)時(shí)仍在正常運(yùn)作)。
可觀測(cè)性數(shù)據(jù)實(shí)時(shí)處理的挑戰(zhàn)
在1.0版本中的Consumer組件,既負(fù)責(zé)將鏈路數(shù)據(jù)寫入到Hbase/HDFS中,又負(fù)責(zé)將鏈路數(shù)據(jù)計(jì)算成指標(biāo)存儲(chǔ)到LinDB中。兩個(gè)流程可視為同步的流程,但前者可接受數(shù)分鐘的延遲,后者要求達(dá)到實(shí)時(shí)的時(shí)效性。當(dāng)時(shí)Hbase集群受限于機(jī)器性能與規(guī)模,經(jīng)常在數(shù)據(jù)熱點(diǎn)時(shí)會(huì)寫入抖動(dòng),進(jìn)而造成指標(biāo)計(jì)算抖動(dòng),影響可用性。因此,我們迫切需要拆分鏈路寫入模塊與指標(biāo)計(jì)算模塊。
在選型實(shí)時(shí)計(jì)算引擎時(shí),我們考慮到需求場(chǎng)景是:
- 能靈活的配置鏈路數(shù)據(jù)的計(jì)算規(guī)則,最好能動(dòng)態(tài)調(diào)整;
- 能水平擴(kuò)展,以適應(yīng)業(yè)務(wù)的快速發(fā)展;
- 數(shù)據(jù)輸出與既有系統(tǒng)(如LinDB與Kafka)無縫銜接;
很遺憾的是,彼時(shí)業(yè)界無現(xiàn)成的拿來即用的大數(shù)據(jù)流處理產(chǎn)品。我們就基于復(fù)雜事件處理(CEP)引擎Esper實(shí)現(xiàn)了一個(gè)類SQL的實(shí)時(shí)數(shù)據(jù)計(jì)算平臺(tái)--Shaka。Shaka包括“Shaka Console”和“Shaka Container”兩個(gè)模塊。Shaka Console由用戶在圖形化界面上使用,來配置數(shù)據(jù)處理流程(Pipeline)、集群、數(shù)據(jù)源等信息。用戶完成Pipeline配置后,Shaka Console會(huì)將變更推送到Zookeeper上。無狀態(tài)的Shaka Container會(huì)監(jiān)聽Zookeeper上的配置變更,根據(jù)自己所屬的集群去更新內(nèi)部運(yùn)行的Component組件。而各Component實(shí)現(xiàn)了各種數(shù)據(jù)的處理邏輯:消費(fèi)Kafka數(shù)據(jù)、處理Trace/Metric數(shù)據(jù)、Metric聚合、運(yùn)行Esper邏輯等。
Trace數(shù)據(jù)和Metric格式轉(zhuǎn)換成固定的格式后,剩下來按需編寫Esper語句就能生成所需的指標(biāo)了。如下文所示的Esper語句,就能將類型為Transaction的Trace數(shù)據(jù)計(jì)算成以“{appId}.transaction”的指標(biāo)(若Consumer中以編碼方式實(shí)現(xiàn),約需要近百行代碼)。經(jīng)過這次的架構(gòu)升級(jí),Trace數(shù)據(jù)能快速的轉(zhuǎn)化為實(shí)時(shí)的Metric數(shù)據(jù),并且對(duì)于業(yè)務(wù)的可觀測(cè)性需求,只用改改SQL語句就能快速滿足,顯著降低了開發(fā)成本和提升了開發(fā)效率。
@Name('transaction')@Metric(name = '{appId}.transaction', tags = {'type', 'name', 'status', 'ezone', 'hostName'}, fields = {'timerCount', 'timerSum', 'timerMin', 'timerMax'}, sampling = 'sampling')select header.ezone as ezone, header.appId as appId, header.hostName as hostName, type as type, name as name, status as status, trunc_sec(timestamp, 10) as timestamp, f_sum(sum(duration)) as timerSum, f_sum(count(1)) as timerCount, f_max(max(duration)) as timerMax, f_min(min(duration)) as timerMin, sampling('Timer', duration, header.msg) as samplingfrom transactiongroup by header.appId, type, name, header.hostName, header.ezone, status, trunc_sec(timestamp, 10);
新的UI、更豐富的中間件數(shù)據(jù)
1.0版本的前端UI,是集成在Console項(xiàng)目中基于Angular V1開發(fā)的。我們迫切希望能做到前后端分離,各司其職。于是基于Angular V2的若干個(gè)月開發(fā),新的Portal組件登場(chǎng)。得益于Angular的數(shù)據(jù)綁定機(jī)制,新的ETrace UI各組件間聯(lián)動(dòng)更自然,排查故障更方便。
餓了么自有中間件的研發(fā)進(jìn)程也在不斷前行,在可觀測(cè)性的打通上也不斷深化。2.0階段,我們進(jìn)一步集成了--Redis、Queue、ElasticSearch等等,覆蓋了餓了么所有的中間件,讓可觀測(cè)性無死角。
殺手級(jí)功能:指標(biāo)查看與鏈路查看的無縫整合
傳統(tǒng)的可觀測(cè)性系統(tǒng)提供的排障方式大致是:接收?qǐng)?bào)警(alert)--查看指標(biāo)(Metrics)--登陸機(jī)器--搜索日志(Trace/Log),而ETrace通過Metric與Trace的整合,能讓用戶直接在UI上通過點(diǎn)擊就能定位絕大部分問題,顯著拔高了用戶的使用體驗(yàn)與排障速度。
某個(gè)排查場(chǎng)景如:用戶發(fā)現(xiàn)總量異常突然增加,可在界面上篩選機(jī)房、異常類型等找到實(shí)際突增的某個(gè)異常,再在曲線上直接點(diǎn)擊數(shù)據(jù)點(diǎn),就會(huì)彈出對(duì)應(yīng)時(shí)間段的異常鏈路信息。鏈路上有詳細(xì)的上下游信息,能幫助用戶定位故障。
它的實(shí)現(xiàn)原理如上圖所示。具體的,前文提到的實(shí)時(shí)計(jì)算模塊Shaka將Trace數(shù)據(jù)計(jì)算成Metric數(shù)據(jù)時(shí),會(huì)額外以抽樣的方式將Trace上的RequsetId與RpcId也寫到Metric上(即上文Esper語句中,生成的Metric中的sampling字段)。這種Metric數(shù)據(jù)會(huì)被Consumer模塊消費(fèi)并寫入到Hbase一張Sampling表中。
用戶在前端Portal的指標(biāo)曲線上點(diǎn)擊某個(gè)點(diǎn)時(shí),會(huì)構(gòu)建一個(gè)Sampling的查詢請(qǐng)求。該請(qǐng)求會(huì)帶上:該曲線的指標(biāo)名、數(shù)據(jù)點(diǎn)的起止時(shí)間、用戶選擇過濾條件(即Tags)。Consumer基于這些信息構(gòu)建一個(gè)Hbase的RegexStringComparator的Scan查詢。查詢結(jié)果中可能會(huì)包含多個(gè)結(jié)果,對(duì)應(yīng)著該時(shí)間點(diǎn)內(nèi)數(shù)據(jù)點(diǎn)(Metric)上發(fā)生的多個(gè)調(diào)用鏈路(Trace),繼而拿著結(jié)果中的RequestId+RpcId再去查詢一次Hbase/HDFS存儲(chǔ)就能獲得鏈路原文。(注:實(shí)際構(gòu)建Hbase Rowkey時(shí)Tag部分存的是其Hashcode而不是原文String。)
眾多轉(zhuǎn)崗、離職的餓了么小伙伴,最念念不忘不完的就是這種“所見即所得”的可觀測(cè)性排障體驗(yàn)。
報(bào)警Watchdog 1.0
在應(yīng)用可觀測(cè)性基本全覆蓋之后,報(bào)警的需求自然成了題中之義。技術(shù)選型上,根據(jù)我們?cè)趯?shí)時(shí)計(jì)算模塊Shaka上收獲的經(jīng)驗(yàn),決定再造一個(gè)基于實(shí)時(shí)數(shù)據(jù)的報(bào)警系統(tǒng)--Watchdog。
實(shí)時(shí)計(jì)算模塊Shaka中已經(jīng)將Trace數(shù)據(jù)計(jì)算成指標(biāo)Metrics,報(bào)警模塊只需消費(fèi)這些數(shù)據(jù),再結(jié)合用戶配置的報(bào)警規(guī)則產(chǎn)出報(bào)警事件即可。因此,我們選型使用Storm作為流式計(jì)算平臺(tái),在Spount層次根據(jù)報(bào)警規(guī)則過濾和分流數(shù)據(jù),在Bolt層中Esper引擎運(yùn)行著由用戶配置的報(bào)警規(guī)則轉(zhuǎn)化成Esper語句并處理分流后的Metric數(shù)據(jù)。若有符合Esper規(guī)則的數(shù)據(jù),即生成一個(gè)報(bào)警事件alert。Watchdog Portal模塊訂閱Kafka中的報(bào)警事件,再根據(jù)具體報(bào)警的觸達(dá)方式通知到用戶。默認(rèn)Esper引擎中數(shù)據(jù)聚合時(shí)間窗口為1分鐘,所以整個(gè)數(shù)據(jù)處理流程的時(shí)延約為1分鐘左右。
Metrics API與LinDB 2.0:
在ETrace 1.0階段,我們只提供了Trace相關(guān)的API,LinDB僅供內(nèi)部存儲(chǔ)使用。用戶逐步的意識(shí)到如果能將“指標(biāo)”與“鏈路”整合起來,就能發(fā)揮更大的功用。因此我們?cè)贓Trace-Agent中新增了Metrics相關(guān)的API:
// 計(jì)數(shù)器類型Trace.newCounter(String metricName).addTags(Map<String, String> tags).count(int value);// 耗時(shí)與次數(shù)Trace.newTimer(String metricName).addTags(Map<String, String> tags).value(int value);// 負(fù)載大小與次數(shù)Trace.newPayload(String metricName).addTags(Map<String, String> tags).value(int value);// 單值類型Trace.newGauge(String metricName).addTags(Map<String, String> tags).value(int value);
基于這些API,用戶可以在代碼中針對(duì)他的業(yè)務(wù)邏輯進(jìn)行指標(biāo)埋點(diǎn),為后來可觀測(cè)性大一統(tǒng)提供了實(shí)現(xiàn)條件。在其他組件同步開發(fā)時(shí),我們也針對(duì)LinDB做了若干優(yōu)化,提升了寫入性能與易用性:
- 增加Histogram、Gauge、Payload、Ratio多種指標(biāo)數(shù)據(jù)類型;
- 從1.0版本的每條指標(biāo)數(shù)據(jù)都調(diào)用一次RocksDB的API進(jìn)行寫入,改成先在內(nèi)存中聚合一段時(shí)間,再通過RocksDB的API進(jìn)行批量寫入文件。
3.0:推陳出新,融會(huì)貫通
可觀測(cè)性系統(tǒng)大一統(tǒng)
在2017年的餓了么,除了ETrace外還有多套可觀測(cè)性系統(tǒng):基于Statsd/Graphite的業(yè)務(wù)可觀測(cè)性系統(tǒng)、基于InfluxDB的基礎(chǔ)設(shè)施可觀測(cè)性系統(tǒng)。后兩者都集成Grafana上,用戶可以去查看他的業(yè)務(wù)或者機(jī)器的詳細(xì)指標(biāo)。但實(shí)際排障場(chǎng)景中,用戶還是需要在多套系統(tǒng)間來回切換:根據(jù)Grafana上的業(yè)務(wù)指標(biāo)感知業(yè)務(wù)故障,到ETrace上查看具體的SOA/DB故障,再到Grafana上去查看具體機(jī)器的網(wǎng)絡(luò)或磁盤IO指標(biāo)。雖然,我們也開發(fā)了Grafana的插件來集成LinDB的數(shù)據(jù)源,但因本質(zhì)上差異巨大的系統(tǒng)架構(gòu),還是讓用戶“疲于奔命”式的來回切換系統(tǒng),用戶難以有統(tǒng)一的可觀測(cè)性體驗(yàn)。因此2018年初,我們下定決心:將多套可觀測(cè)性系統(tǒng)合而為一,打通“業(yè)務(wù)可觀測(cè)性+應(yīng)用可觀測(cè)性+基礎(chǔ)設(shè)施可觀測(cè)性”,讓ETrace真正成為餓了么的一站式可觀測(cè)性平臺(tái)。
LinDB 3.0:
所謂“改造”未動(dòng),“存儲(chǔ)”先行。想要整合InfluxDB與Statsd,先要研究他們與LinDB的異同。我們發(fā)現(xiàn),InfluxDB是支持一個(gè)指標(biāo)名(Measurement)上有多個(gè)Field Key的。如,InfluxDB可能有以下指標(biāo):
measurement=census, fields={butterfiles=12, honeybees=23}, tags={location=SH, scientist=jack}, timestamp=2015-08-18T00:06:00Z
若是LinDB 2.0的模式,則需要將上述指標(biāo)轉(zhuǎn)換成兩個(gè)指標(biāo):
measurement=census, field={butterfiles=12}, tags={location=SH, scientist=jack}, timestamp=2015-08-18T00:06:00Zmeasurement=census, field={honeybees=23}, tags={location=SH, scientist=jack}, timestamp=2015-08-18T00:06:00Z
可以想見在數(shù)據(jù)存儲(chǔ)與計(jì)算效率上,單Field模式有著極大的浪費(fèi)。但更改指標(biāo)存儲(chǔ)的Schema,意味著整個(gè)數(shù)據(jù)處理鏈路都需要做適配和調(diào)整,工作量和改動(dòng)極大。然而不改就意味著“將就”,我們不能忍受對(duì)自己要求的降低。因此又經(jīng)過了幾個(gè)月的爆肝研發(fā),LinDB 3.0開發(fā)完成。
這次改動(dòng),除了升級(jí)到指標(biāo)多Fields模式外,還有以下優(yōu)化點(diǎn):
經(jīng)過這次大規(guī)模優(yōu)化后,從最初的每日5T指標(biāo)數(shù)據(jù)漲到如今的每日200T數(shù)據(jù),LinDB 3.0都經(jīng)受住了考驗(yàn)。指標(biāo)查詢的響應(yīng)時(shí)間的99分位線為200ms。詳細(xì)設(shè)計(jì)細(xì)節(jié)可參看文末的分布式時(shí)序數(shù)據(jù)庫 - LinDB。
將Statsd指標(biāo)轉(zhuǎn)成LinDB指標(biāo)
Statsd是餓了么廣泛使用的業(yè)務(wù)指標(biāo)埋點(diǎn)方案,各機(jī)房有一個(gè)數(shù)十臺(tái)機(jī)器規(guī)模的Graphite集群。考慮到業(yè)務(wù)的核心指標(biāo)都在Statsd上,并且各個(gè)AppId以ETrace Metrics API替換Statsd是一個(gè)漫長的過程(也確實(shí)是,前前后后替換完成就花了將近一年時(shí)間)。為了減少對(duì)用戶與NOC團(tuán)隊(duì)的影響,我們決定:用戶更新代碼的同時(shí),由ETrace同時(shí)“兼容”Statsd的數(shù)據(jù)。
得益于餓了么強(qiáng)大的中間件體系,業(yè)務(wù)在用Statsd API埋點(diǎn)的同時(shí)會(huì)“自動(dòng)”記一條特殊的Trace數(shù)據(jù),攜帶上Statsd的Metric數(shù)據(jù)。那么只要處理Trace數(shù)據(jù)中的Statsd埋點(diǎn),我們就能將大多數(shù)Statsd指標(biāo)轉(zhuǎn)化為LinDB指標(biāo)。如下圖:多個(gè)Statsd指標(biāo)會(huì)轉(zhuǎn)為同一個(gè)LinDB指標(biāo)。
// statsd:stats.app.myAppName.order.from_ios.success 32stats.app.myAppName.order.from_android.success 29stats.app.myAppName.order.from_pc.failure 10stats.app.myAppName.order.from_openapi.failure 5// lindb:MetricName: myAppName.orderTags: "tag1"=[from_ios, from_android,from_pc, from_openapi] "tag2"=[success, failure]
之前我們的實(shí)時(shí)計(jì)算模塊Shaka就在這里派上了大用場(chǎng):只要再新增一路數(shù)據(jù)處理流程即可。如下圖,新增一條Statsd數(shù)據(jù)的處理Pipeline,并輸出結(jié)果到LinDB。在用戶的代碼全部從Statsd API遷移到ETrace API后,這一路處理邏輯即可移除。
將InfluxDB指標(biāo)轉(zhuǎn)成LinDB指標(biāo)
InfluxDB主要用于機(jī)器、網(wǎng)絡(luò)設(shè)備等基礎(chǔ)設(shè)施的可觀測(cè)性數(shù)據(jù)。餓了么每臺(tái)機(jī)器上,都部署了一個(gè)ESM-Agent。它負(fù)責(zé)采集機(jī)器的物理指標(biāo)(CPU、網(wǎng)絡(luò)協(xié)議、磁盤、進(jìn)程等),并在特定設(shè)備上進(jìn)行網(wǎng)絡(luò)嗅探(Smoke Ping)等。這個(gè)數(shù)據(jù)采集Agent原由Python開發(fā),在不斷需求堆疊之后,已龐大到難以維護(hù);并且每次更新可觀測(cè)邏輯,都需要全量發(fā)布每臺(tái)機(jī)器上的Agent,導(dǎo)致每次Agent的發(fā)布都令人心驚膽戰(zhàn)。
我們從0開始,以Golang重新開發(fā)了一套ESM-Agent,做了以下改進(jìn):
從ETrace到EMonitor,不斷升級(jí)的可觀測(cè)性體驗(yàn)
2017年底,我們團(tuán)隊(duì)終于迎來了一名正式的前端開發(fā)工程師,可觀測(cè)性團(tuán)隊(duì)正式從后端開發(fā)寫前端的狀態(tài)中脫離出來。在之前的Angular的開發(fā)體驗(yàn)中,我們深感“狀態(tài)轉(zhuǎn)換”的控制流程甚為繁瑣,并且開發(fā)的組件難以復(fù)用(雖然其后版本的Angular有了很大的改善)。在調(diào)用當(dāng)時(shí)流行的前端框架后,我們?cè)赩ue與React之中選擇了后者,輔以Ant Design框架,開發(fā)出了媲美Grafana的指標(biāo)看版與便利的鏈路看板,并且在PC版本之外還開發(fā)了移動(dòng)端的定制版本。我們亦更名了整個(gè)可觀測(cè)性產(chǎn)品,從“ETrace”更新為“EMonitor”:不僅僅是鏈路可觀測(cè)性系統(tǒng),更是餓了么的一站式可觀測(cè)性平臺(tái)。
可觀測(cè)性數(shù)據(jù)的整合:業(yè)務(wù)指標(biāo) + 應(yīng)用鏈路 + 基礎(chǔ)設(shè)施指標(biāo) + 中間件指標(biāo)
在指標(biāo)系統(tǒng)都遷移到LinDB后,我們?cè)贓Monitor上集成了“業(yè)務(wù)指標(biāo) + 應(yīng)用鏈路 + 基礎(chǔ)設(shè)施指標(biāo) + 中間件指標(biāo)”的多層次的可觀測(cè)性數(shù)據(jù),讓用戶能在一處觀測(cè)它的業(yè)務(wù)數(shù)據(jù)、排查業(yè)務(wù)故障、深挖底層基礎(chǔ)設(shè)施的數(shù)據(jù)。
可觀測(cè)性場(chǎng)景的整合:指標(biāo) + 鏈路 + 報(bào)警
在可觀測(cè)性場(chǎng)景上,“指標(biāo)看板”用于日常業(yè)務(wù)盯屏與宏觀業(yè)務(wù)可觀測(cè)性,“鏈路”作為應(yīng)用排障與微觀業(yè)務(wù)邏輯透出,“報(bào)警”則實(shí)現(xiàn)可觀測(cè)性自動(dòng)化,提高應(yīng)急響應(yīng)效率。
靈活的看板配置與業(yè)務(wù)大盤
在指標(biāo)配置上,我們提供了多種圖表類型--線圖、面積圖、散點(diǎn)圖、柱狀圖、餅圖、表格、文本等,以及豐富的自定義圖表配置項(xiàng),能滿足用戶不同數(shù)據(jù)展示需求。
在完成單個(gè)指標(biāo)配置后,用戶需要將若干個(gè)指標(biāo)組合成所需的指標(biāo)看板。用戶在配置頁面中,先選擇待用的指標(biāo),再通過拖拽的方式,配置指標(biāo)的布局便可實(shí)時(shí)預(yù)覽布局效果。一個(gè)指標(biāo)可被多個(gè)看板引用,指標(biāo)的更新也會(huì)自動(dòng)同步到所有看板上。為避免指標(biāo)配置錯(cuò)誤而引起歧義,我們也開發(fā)了“配置歷史”的功能,指標(biāo)、看板等配置都能回滾到任意歷史版本上。
看板配置是靜態(tài)圖表組合,而業(yè)務(wù)大盤提供了生動(dòng)的業(yè)務(wù)邏輯視圖。用戶可以根據(jù)他的業(yè)務(wù)場(chǎng)景,將指標(biāo)配置整合成一張宏觀的業(yè)務(wù)圖。
第三方系統(tǒng)整合:變更系統(tǒng) + SLS日志
因每條報(bào)警信息和指標(biāo)配置信息都與AppId關(guān)聯(lián),那么在指標(biāo)看板上可同步標(biāo)記出報(bào)警的觸發(fā)時(shí)間。同理,我們拉取了餓了么變更系統(tǒng)的應(yīng)用變更數(shù)據(jù),將其標(biāo)注到對(duì)應(yīng)AppId相關(guān)的指標(biāo)上。在故障發(fā)生時(shí),用戶查看指標(biāo)數(shù)據(jù)時(shí),能根據(jù)有無變更記錄、報(bào)警記錄來初步判斷故障原因。
餓了么的日志中間件能自動(dòng)在記錄日志時(shí)加上對(duì)應(yīng)的ETrace的RequestId等鏈路信息。如此,用戶查看SLS日志服務(wù)時(shí),能反查到整條鏈路的RequestId;而EMonitor也在鏈路查看頁面,拼接好了該應(yīng)用所屬的SLS鏈接信息,用戶點(diǎn)擊后能直達(dá)對(duì)應(yīng)的SLS查看日志上下文。
使用場(chǎng)景的整合:桌面版 + 移動(dòng)版
除提供桌面版的EMonitor外,我們還開發(fā)了移動(dòng)版的EMonitor,它也提供了大部分可觀測(cè)性系統(tǒng)的核心功能--業(yè)務(wù)指標(biāo)、應(yīng)用指標(biāo)、報(bào)警信息等。移動(dòng)版EMonitor能內(nèi)嵌于釘釘之中,打通了用戶認(rèn)證機(jī)制,幫助用戶隨時(shí)隨地掌握所有的可觀測(cè)性信息。
為了極致的體驗(yàn),精益求精
為了用戶的極致使用體驗(yàn),我們?cè)贓Monitor上各功能使用上細(xì)細(xì)打磨,這里僅舉幾個(gè)小例子:
- 我們?yōu)闃O客開發(fā)者實(shí)現(xiàn)了若干鍵盤快捷鍵。例如,“V”鍵就能展開查看指標(biāo)大圖。
- 圖上多條曲線時(shí),點(diǎn)擊圖例是默認(rèn)單選,目的是讓用戶只看他關(guān)心的曲線。此外,若是“Ctrl+鼠標(biāo)點(diǎn)擊”則是將其加選擇的曲線中。這個(gè)功能在一張圖幾十條曲線時(shí),對(duì)比幾個(gè)關(guān)鍵曲線時(shí)尤為有用。
- 為了讓色弱開發(fā)者更容易區(qū)分成功或失敗的狀態(tài),我們針對(duì)性的調(diào)整了對(duì)應(yīng)顏色的對(duì)比度。
成為餓了么一站式可觀測(cè)性平臺(tái)
EMonitor開發(fā)完成后,憑借優(yōu)異的用戶體驗(yàn)與產(chǎn)品集成度,很快在用戶中普及開來。但是,EMonitor要成為餓了么的一站式可觀測(cè)性平臺(tái),還剩下最后一戰(zhàn)--NOC可觀測(cè)性大屏。
NOC可觀測(cè)性大屏替換
餓了么有一套完善的應(yīng)急處理與保障團(tuán)隊(duì),包括7*24值班的NOC(Network Operation Center)團(tuán)隊(duì)。在NOC的辦公區(qū)域,有一整面墻上都是可觀測(cè)性大屏,上面顯示著餓了么的實(shí)時(shí)的各種業(yè)務(wù)曲線。下圖為網(wǎng)上找的一張示例圖,實(shí)際餓了么的NOC大屏比它更大、數(shù)據(jù)更多。
當(dāng)時(shí)這個(gè)可觀測(cè)大屏是將Grafana的指標(biāo)看版投影上去。我們希望將NOC大屏也替換成EMonitor的看版。如前文所說,我們逐步將用戶的Statsd指標(biāo)數(shù)據(jù)轉(zhuǎn)換成了LinDB指標(biāo),在NOC團(tuán)隊(duì)的協(xié)助下,一個(gè)一個(gè)將Grafana的可觀測(cè)性指標(biāo)“搬”到EMonitor上。此外,在原來白色主題的EMonitor之上,我們開發(fā)了黑色主題以適配投屏上墻的效果(白色背景投屏太刺眼)。
終于趕在2018年的雙十一之前,EMonitor正式入駐NOC可觀測(cè)大屏。在雙十一當(dāng)天,眾多研發(fā)擠在NOC室看著墻上的EMonitor看版上的業(yè)務(wù)曲線不斷飛漲,作為可觀測(cè)性團(tuán)隊(duì)的一員,這份自豪之情由衷而生。經(jīng)此一役,EMonitor真正成為了餓了么的“一站式可觀測(cè)性平臺(tái)”,Grafana、Statsd、InfluxDB等都成了過去時(shí)。
報(bào)警Watchdog 2.0
同樣在EMonitor之前,亦有Statsd與InfluxDB對(duì)應(yīng)的多套報(bào)警系統(tǒng)。用戶若想要配置業(yè)務(wù)報(bào)警、鏈路報(bào)警、機(jī)器報(bào)警,需要輾轉(zhuǎn)多個(gè)報(bào)警系統(tǒng)之間。各系統(tǒng)的報(bào)警的配置規(guī)則、觸達(dá)體驗(yàn)亦是千差萬別。Watchdog報(bào)警系統(tǒng)也面臨著統(tǒng)一融合的挑戰(zhàn)。
- 在調(diào)研其他系統(tǒng)的報(bào)警規(guī)則實(shí)現(xiàn)后,Watchdog中仍以LinDB的指標(biāo)作為元數(shù)據(jù)實(shí)現(xiàn)。
- 針對(duì)其他報(bào)警系統(tǒng)的有顯著區(qū)別的訂閱模式,我們提出了"報(bào)警規(guī)則+一個(gè)規(guī)則多個(gè)訂閱標(biāo)簽+一個(gè)用戶訂閱多個(gè)標(biāo)簽"的方式,完美遷移了幾乎其他系統(tǒng)所有的報(bào)警規(guī)則與訂閱關(guān)系。
- 其他各系統(tǒng)在報(bào)警觸達(dá)與觸達(dá)內(nèi)容上也略有不同。我們統(tǒng)一整合成“郵件+短信+釘釘+語音外呼”四種通知方式,并且提供可參數(shù)化的自定義Markdown模板,讓用戶可自己定時(shí)報(bào)警信息。
經(jīng)過一番艱苦的報(bào)警配置與邏輯整合后,我們?yōu)橛脩簟白詣?dòng)”遷移了上千個(gè)報(bào)警規(guī)則,并最終為他們提供了一個(gè)統(tǒng)一的報(bào)警平臺(tái)。
報(bào)警,更精準(zhǔn)的報(bào)警
外賣行業(yè)的業(yè)務(wù)特性是業(yè)務(wù)的午高峰與晚高峰,在業(yè)務(wù)曲線上便是兩個(gè)波峰的形狀。這樣的可觀測(cè)數(shù)據(jù),自然難以簡單使用閾值或比率來做判斷。即使是根據(jù)歷史同環(huán)比、3-Sigma、移動(dòng)平均等規(guī)則,也難以適應(yīng)餓了么的可觀測(cè)性場(chǎng)景。因?yàn)椋I了么的業(yè)務(wù)曲線并非一成不變,它受促銷、天氣因素、區(qū)域、壓測(cè)等因素影響。開發(fā)出一個(gè)自適應(yīng)業(yè)務(wù)曲線變化的報(bào)警算法,勢(shì)在必行。
我們經(jīng)過調(diào)研既有規(guī)則,與餓了么的業(yè)務(wù)場(chǎng)景,推出了全新的“趨勢(shì)”報(bào)警。簡要算法如下:
- 計(jì)算歷史10天的指標(biāo)數(shù)據(jù)中值作為基線。其中這10天都取工作日或非工作日。不取10天的均值而取中值是為了減少壓測(cè)或機(jī)房流量切換造成的影響。
- 根據(jù)二階滑動(dòng)平均算法,得到滑動(dòng)平均值與當(dāng)前實(shí)際值的差值。
- 將基線與差值相加作為預(yù)測(cè)值。
- 根據(jù)預(yù)測(cè)值的數(shù)量級(jí),計(jì)算出波動(dòng)的幅度(如上界與下界的數(shù)值)。
- 若當(dāng)前值不在預(yù)測(cè)值與波動(dòng)幅度確定的上下界之中,則觸發(fā)報(bào)警。
如上圖所示,22點(diǎn)01分的實(shí)際值因不在上下界所限定的區(qū)域之中,會(huì)觸發(fā)報(bào)警。但從后續(xù)趨勢(shì)來看,該下降趨勢(shì)符合預(yù)期,因此實(shí)際中還會(huì)輔以“偏離持續(xù)X分鐘”來修正誤報(bào)。(如該例中,可增加“持續(xù)3分鐘才報(bào)警”的規(guī)則,該點(diǎn)的數(shù)據(jù)便不會(huì)報(bào)警)算法中部分參數(shù)為經(jīng)驗(yàn)值,而其中波動(dòng)的閾值參數(shù)用戶可按照自己業(yè)務(wù)調(diào)整。用戶針對(duì)具備業(yè)務(wù)特征的曲線,再也不用費(fèi)心的去調(diào)整參數(shù),配置上默認(rèn)的“趨勢(shì)”規(guī)則就可以覆蓋大多數(shù)的可觀測(cè)性場(chǎng)景,目前“趨勢(shì)”報(bào)警在餓了么廣泛運(yùn)用。
智能可觀測(cè)性:根因分析,大顯神威
作為AIOPS中重要的一環(huán),根因分析能幫助用戶快速定位故障,縮短故障響應(yīng)時(shí)間,減少故障造成的損失。2020年初,我們結(jié)合餓了么場(chǎng)景,攻堅(jiān)克難,攻破“指標(biāo)下鉆”、“根因分析”兩大難關(guān),在EMonitor上成功落地。
根因分析最大的難點(diǎn)在于:包含復(fù)雜維度的指標(biāo)數(shù)據(jù)難以找到真正影響數(shù)據(jù)波動(dòng)的具體維度;孤立的指標(biāo)數(shù)據(jù)也難以分析出應(yīng)用上下游依賴引起的故障根因。例如,某個(gè)應(yīng)用的異常指標(biāo)突增,當(dāng)前我們只能知道突增的異常名、機(jī)房維度的異常分布、機(jī)器維度的異常分布等,只有用戶手工去點(diǎn)擊異常指標(biāo)看來鏈路之后,才能大致判斷是哪個(gè)SOA方法/DB請(qǐng)求中的異常。繼而用戶根據(jù)異常鏈路的環(huán)節(jié),去追溯上游或下游的應(yīng)用,重復(fù)類似的排查過程,最后以人工經(jīng)驗(yàn)判斷出故障點(diǎn)。
因此,在“指標(biāo)下鉆”上,我們針對(duì)目標(biāo)指標(biāo)的曲線,細(xì)分成最精細(xì)的每個(gè)維度數(shù)據(jù)(指標(biāo)group by待分析的tag維度),使用KMeans聚類找出故障數(shù)據(jù)的各維度的最大公共特征,依次計(jì)算找到最優(yōu)的公共特征,如此便能找到曲線波動(dòng)對(duì)應(yīng)的維度信息。
其次,在鏈路數(shù)據(jù)計(jì)算時(shí),我們就能將額外的上下游附加信息附加到對(duì)應(yīng)的指標(biāo)之中。如,可在異常指標(biāo)中追加一個(gè)維度來記錄產(chǎn)生異常的SOA方法名。這樣在根據(jù)異常指標(biāo)分析時(shí),能直接定位到是這個(gè)應(yīng)用的那個(gè)SOA方法拋出的異常,接下來“自動(dòng)”分析是SOA下游故障還是自身故障(DB、Cache、GC等)。
在2020.3月在餓了么落地以來,在分析的上百例故障中,根因分析的準(zhǔn)確率達(dá)到90%以上,顯著縮短的故障排查的時(shí)間,幫助各業(yè)務(wù)向穩(wěn)定性建設(shè)目標(biāo)向前跨進(jìn)了一大步。
4.0:繼往開來,乘勢(shì)而上
經(jīng)過4、5年的發(fā)展,風(fēng)云變幻但團(tuán)隊(duì)初心不改,為了讓用戶用好可觀測(cè)性系統(tǒng),EMonitor沒有停下腳步,自我革新,希望讓“天下沒有難用的可觀測(cè)性系統(tǒng)”。我們向集團(tuán)的可觀測(cè)性團(tuán)隊(duì)請(qǐng)教學(xué)習(xí),結(jié)合本地生活自己的技術(shù)體系建設(shè),力爭(zhēng)百尺竿頭更進(jìn)一步,規(guī)劃了以下的EMonitor 4.0的設(shè)計(jì)目標(biāo)。
一、進(jìn)行多租戶化改造,保障核心數(shù)據(jù)的時(shí)延和可靠性
在本地生活的技術(shù)體系與阿里巴巴集團(tuán)技術(shù)體系的不斷深入的融合之中,單元化的部署環(huán)境以及對(duì)可觀測(cè)性數(shù)據(jù)不同程度的可靠性要求,催生了“多租戶化”的設(shè)計(jì)理念。我們可以根據(jù)應(yīng)用類型、數(shù)據(jù)類型、來源等,將可觀測(cè)性數(shù)據(jù)分流到不同的租戶中,再針對(duì)性配置數(shù)據(jù)處理流程及分配處理能力,實(shí)現(xiàn)差異化的可靠性保障能力。
初步我們可以劃分為兩個(gè)集群--核心應(yīng)用集群與非核心應(yīng)用集合,根據(jù)在應(yīng)用上標(biāo)記的“應(yīng)用等級(jí)”將其數(shù)據(jù)自動(dòng)發(fā)送到對(duì)應(yīng)集群中。兩套集群在資源配置上優(yōu)先側(cè)重核心集群,并且完全物理隔離。此外通過配置開關(guān)可動(dòng)態(tài)控制某個(gè)應(yīng)用歸屬的租戶,實(shí)現(xiàn)業(yè)務(wù)的柔性降級(jí),避免當(dāng)下偶爾因個(gè)別應(yīng)用的不正確埋點(diǎn)方式會(huì)影響整體可觀測(cè)可用性的問題。
未來可根據(jù)業(yè)務(wù)發(fā)展進(jìn)一步發(fā)展出業(yè)務(wù)相關(guān)的租戶,如到家業(yè)務(wù)集群、到店業(yè)務(wù)集群等。或者按照區(qū)域的劃分,如彈內(nèi)集群、彈外集群等。
二、打通集團(tuán)彈內(nèi)、彈外的可觀測(cè)性數(shù)據(jù),成為本地生活的一站式可觀測(cè)性平臺(tái)
目前本地生活很多業(yè)務(wù)領(lǐng)域已經(jīng)遷入集團(tuán),在Trace鏈路可觀測(cè)方面,雖然在本地生活上云的項(xiàng)目中,EMonitor已經(jīng)通過中間件改造實(shí)現(xiàn)鷹眼TraceId在鏈路上的傳遞,并記錄了EMonitor RequestId與鷹眼TraceId的映射關(guān)系。但EMonitor與鷹眼在協(xié)議上的天然隔閡仍使得用戶需要在兩個(gè)平臺(tái)間跳轉(zhuǎn)查看同一條Trace鏈路。因此,我們接下來的目標(biāo)是與鷹眼團(tuán)隊(duì)合作,將鷹眼的Trace數(shù)據(jù)集成到EMonitor上,讓用戶能一站式的排查問題。
其次,本地生活上云后,眾多中間件已遷移到云上中間件,如云Redis、云Kafka、云Zookeeper等。對(duì)應(yīng)的可觀測(cè)性數(shù)據(jù)也需要額外登陸到阿里云控制臺(tái)去查看。云上中間的可觀測(cè)性數(shù)據(jù)大多已存儲(chǔ)到Prometheus之中,因此我們計(jì)劃在完成Prometheus協(xié)議兼容后,就與云上中間件團(tuán)隊(duì)合作,將本地生活的云上可觀測(cè)性數(shù)據(jù)集成到EMonitor上。
三、擁抱云原生,兼容Prometheus、OpenTelemetry等開源協(xié)議。
云原生帶來的技術(shù)革新勢(shì)不可擋,本地生活的絕大多數(shù)應(yīng)用已遷移到集團(tuán)的容器化平臺(tái)--ASI上,對(duì)應(yīng)帶來的新的可觀測(cè)環(huán)節(jié)也亟需補(bǔ)全。如,ASI上Prometheus協(xié)議的容器可觀測(cè)性數(shù)據(jù)、Envoy等本地生活PaaS平臺(tái)透出的可觀測(cè)性數(shù)據(jù)與Trace數(shù)據(jù)等。
因此,我們計(jì)劃在原先僅支持LinDB數(shù)據(jù)源的基礎(chǔ)上,增加對(duì)Prometheus數(shù)據(jù)源的支持;擴(kuò)展OpenTelemetry的otel-collector exporter實(shí)現(xiàn),將Open Telemetry協(xié)議的Trace數(shù)據(jù)轉(zhuǎn)換成EMonitor的Trace格式。如此便可補(bǔ)全云原生技術(shù)升級(jí)引起的可觀測(cè)性數(shù)據(jù)缺失,并提供高度的適配性,滿足本地生活的可觀測(cè)性建設(shè)。
結(jié)語
縱觀各大互聯(lián)網(wǎng)公司的產(chǎn)品演進(jìn),技術(shù)產(chǎn)品的走向與命運(yùn)都離不開公司業(yè)務(wù)的發(fā)展軌跡。我們餓了么的技術(shù)人是幸運(yùn)的,能趕上這一波技術(shù)變革的大潮,能夠發(fā)揮聰明才智,打磨出一些為用戶津津樂道的技術(shù)產(chǎn)品。我們EMonitor可觀測(cè)性團(tuán)隊(duì)也為能參與到這次技術(shù)變更中深感自豪,EMonitor能被大家認(rèn)可, 離不開每位參與到餓了么可觀測(cè)性體系建設(shè)的同伴,也感謝各位對(duì)可觀測(cè)性系統(tǒng)提供幫助、支持、建議的伙伴!
作者簡介:柯圣,花名“炸天”,餓了么監(jiān)控技術(shù)組負(fù)責(zé)人。自2016年加入餓了么,長期深耕于可觀測(cè)性領(lǐng)域,全程參與了ETrace到EMonitor的餓了么可觀測(cè)性系統(tǒng)的發(fā)展歷程。
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。