基于SpringBoot 2.x+Sleuth+Zipkin(Rabbitmq+Mysql)構(gòu)建鏈路追蹤系統(tǒng)

背景


? ? ? ? 無論你的系統(tǒng)是龐大的單應(yīng)用架構(gòu)蛮粮,還是采用的微服務(wù)架構(gòu)溅固,只要是調(diào)用過程非常復(fù)雜有缆,都會(huì)存在如何追蹤各個(gè)方法或者服務(wù)間調(diào)用異常如何被開發(fā)和運(yùn)維人員快速定位的問題名秀,為了解決這個(gè)問題励负,你勢(shì)必需要記錄大量的日志。

? ? ? ?舉個(gè)例子匕得,對(duì)于一個(gè)大流量的Web應(yīng)用通常以Stateless方式設(shè)計(jì)继榆,這樣可以更方便的進(jìn)行水平擴(kuò)容。但是隨著應(yīng)用實(shí)例數(shù)量越來越多汁掠,我們查詢?nèi)罩揪驮絹碓嚼щy裕照。在沒有日志系統(tǒng)的情況下,首先我們需要定位到請(qǐng)求的服務(wù)器地址调塌,如果每臺(tái)服務(wù)器都部署了多個(gè)應(yīng)用實(shí)例晋南,我們則需要去每個(gè)應(yīng)用實(shí)例的日志目錄下去找日志文件。每個(gè)服務(wù)可能還會(huì)設(shè)置日志滾動(dòng)策略(如:每200M一個(gè)文件)羔砾,還有日志壓縮歸檔策略负间。

? ? ? ? 如此,我們查詢一條出錯(cuò)信息就要在茫茫多的日志文件里去找到它姜凄,于是使出我們的十八般武藝head less tail grep wc awk count cut政溃,但是如果需要統(tǒng)計(jì)最近3天的某個(gè)接口的異常次數(shù),或者超時(shí)次數(shù)态秧。董虱。。申鱼。除了上面出現(xiàn)的狀況我們還需要考慮:日志量太大如何歸檔愤诱、文本搜索太慢怎么辦?

? ? ? ? 但是對(duì)于故障排查肯定是希望能夠快速的進(jìn)行日志查詢捐友、定位淫半、解決問題,對(duì)于實(shí)時(shí)性要求非常高匣砖。為了解決這個(gè)問題科吭,日志追蹤系統(tǒng)應(yīng)運(yùn)而生。

概念


? ??????先介紹一個(gè)概念:分布式跟蹤猴鲫,或分布式追蹤对人。

????????電商平臺(tái)由數(shù)以百計(jì)的分布式服務(wù)構(gòu)成,每一個(gè)請(qǐng)求路由過來后拂共,會(huì)經(jīng)過多個(gè)業(yè)務(wù)系統(tǒng)并留下足跡牺弄,并產(chǎn)生對(duì)各種Cache或DB的訪問,但是這些分散的數(shù)據(jù)對(duì)于問題排查匣缘,或是流程優(yōu)化都幫助有限猖闪。對(duì)于這么一個(gè)跨進(jìn)程/跨線程的場(chǎng)景鲜棠,匯總收集并分析海量日志就顯得尤為重要。要能做到追蹤每個(gè)請(qǐng)求的完整調(diào)用鏈路培慌,收集調(diào)用鏈路上每個(gè)服務(wù)的性能數(shù)據(jù)豁陆,計(jì)算性能數(shù)據(jù)和比對(duì)性能指標(biāo)(SLA),甚至在更遠(yuǎn)的未來能夠再反饋到服務(wù)治理中吵护,那么這就是分布式跟蹤的目標(biāo)了盒音。在業(yè)界,Twitter 的 zipkin 和淘寶的鷹眼就是類似的系統(tǒng)馅而,它們都起源于 Google Dapper 論文祥诽。

????????整理一下,Google叫Dapper瓮恭,淘寶叫鷹眼雄坪,Twitter叫ZipKin,京東商城叫Hydra屯蹦,eBay叫Centralized Activity Logging (CAL)维哈,大眾點(diǎn)評(píng)網(wǎng)叫CAT,其底層實(shí)現(xiàn)的追蹤邏輯登澜,幾乎都是一樣的阔挠。

分布式追蹤系統(tǒng)的設(shè)計(jì)理念


(1)低侵入性——作為非業(yè)務(wù)組件,應(yīng)當(dāng)盡可能少侵入或者無侵入其他業(yè)務(wù)系統(tǒng)脑蠕,對(duì)于使用方透明购撼,減少開發(fā)人員的負(fù)擔(dān);

(2)靈活的應(yīng)用策略——可以(最好隨時(shí))決定所收集數(shù)據(jù)的范圍和粒度谴仙;

(3)時(shí)效性——從數(shù)據(jù)的收集和產(chǎn)生迂求,到數(shù)據(jù)計(jì)算和處理,再到最終展現(xiàn)狞甚,都要求盡可能快锁摔;

(4)決策支持——這些數(shù)據(jù)是否能在決策支持層面發(fā)揮作用,特別是從 DevOps 的角度哼审;

(5)可視化才是王道。

Zipkin出場(chǎng)


? ? ? ? 在眾多的追蹤系統(tǒng)中孕豹,本文只是對(duì)Zipkin的應(yīng)用做說明涩盾。

? ? ? ? 最初接觸Zipkin,是在《Spring Cloud 微服務(wù)實(shí)戰(zhàn)》這本書中的 Spring Cloud Sleuth章節(jié)励背,按照這個(gè)章節(jié)寫的例子學(xué)習(xí)下來春霍,踩了無數(shù)個(gè)坑,弄的我是云里霧里叶眉。索性放棄書上的例子址儒,直接看 Zipkin官網(wǎng)(https://zipkin.io)和Spinrg官網(wǎng)中關(guān)于Cloud Sleuth章節(jié)(https://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/2.1.2.RELEASE/multi/multi_spring-cloud-sleuth.html)芹枷,同時(shí)查閱了多個(gè)網(wǎng)絡(luò)上的文章,才發(fā)現(xiàn)隨著Spring boot 2.X的問世莲趣,Spring Cloud Sleuth關(guān)于Zipkin的實(shí)現(xiàn)方式發(fā)生了非常大的變化鸳慈。(在寫這篇文章時(shí),Zipkin的版本是V2.14.0)

? ??????Spring Cloud Sleuth 在Spring Boot 1.x時(shí)代喧伞,是對(duì)Zipkin做一個(gè)完全整合走芋,不僅實(shí)現(xiàn)了以 HTTP 的方式收集跟蹤信息,還實(shí)現(xiàn)了通過消息中間件來對(duì)跟蹤信息進(jìn)行異步收集的封裝潘鲫。就連Zipkin服務(wù)器翁逞,也做了一層封裝。而到了 Spring Boot 2.0 之后?Zipkin 不再推薦我們?cè)僮远x Server 端了溉仑,Sleuth專注于對(duì)Dapper 中的算法進(jìn)行封裝挖函,spring-cloud-starter-zipkin?只是對(duì)Zipkin客戶端的封裝,對(duì)于Sleuth在工程中如何使用浊竟,Spring官網(wǎng)上是這樣寫的:

\bullet Only Sleuth (log correlation):如果你只想使用Sleuth功能怨喘,而不想與Zipkin做集成的話,那么你只需要引入spring-cloud-starter-sleuth就可以了逐沙。我覺得哲思,這種方式,對(duì)于普通使用者是很少會(huì)這樣用的吩案。是否是給那些牛到自己開發(fā)追蹤服務(wù)的人準(zhǔn)備的棚赔?誰知道呢!

\bullet Sleuth with Zipkin via HTTP :不重復(fù)發(fā)明輪子徘郭,是本人的一貫主張靠益。如果你想使用Sleuth并通過HTTP方式集成ZipkinServer,你只需要引入spring-cloud-starter-zipkin 就可以了残揉。你可能會(huì)問:spring-cloud-starter-sleuth不需要引入了嗎? 我的回答是:需要胧后,但它會(huì)被spring-cloud-starter-zipkin間接依賴而自動(dòng)引入的。

\bullet Sleuth with Zipkin over RabbitMQ or Kafka :最后一種使用方式是抱环,如果你不想通過HTPP方式集成ZipkinServer壳快,而是通過RabbitMQ或者Kafka這些消息中間件做異步消息處理的話(筆者推薦這種用法),你除了需要引入spring-cloud-starter-zipkin镇草,還需要引入spring-rabbit(本文以Rabbit為例)眶痰。還有一點(diǎn)就是:如果使用了消息中間件傳遞消息,那么Zipkin的服務(wù)端也需要做相應(yīng)的配置梯啤,才能監(jiān)聽處理消息竖伯。

RabbitMQ相關(guān)參數(shù)配置


spring:

? rabbitmq:

? ? host: 10.10.10.10

? ? port: 5672

? ? username: guest

? ? password: guest

同時(shí),在啟動(dòng)Zipkin服務(wù)端的時(shí)候,添加以上相同的Rabiit配置

D:\>java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=10.10.10.10?

端口如果不寫默認(rèn)是5672七婴,用戶名密碼也是采用的默認(rèn)值祟偷,如果你的配置不是采用默認(rèn)值,需要維護(hù)相應(yīng)參數(shù)打厘。

啟動(dòng)服務(wù)


啟動(dòng)集成了Sleuth的服務(wù)和Zipkin 服務(wù)端修肠,進(jìn)行訪問帶多級(jí)調(diào)用的服務(wù)(省略具體操作),打開Zipkin的UI界面http://localhost:9411/zipkin/? 婚惫,如下圖:

可以看到氛赐,剛才的調(diào)用鏈已經(jīng)可以查詢到了。點(diǎn)擊某條記錄先舷,進(jìn)入調(diào)用詳細(xì)頁面艰管。

可以看到每個(gè)服務(wù)的調(diào)用時(shí)間,時(shí)長蒋川,是否異常等信息牲芋。這樣,你就可以快速定位那些響應(yīng)時(shí)間超長的請(qǐng)求或者發(fā)生異常的請(qǐng)求捺球。

存儲(chǔ)


Zipkin最初是為在Cassandra上存儲(chǔ)數(shù)據(jù)而構(gòu)建的缸浦,因?yàn)镃assandra是可擴(kuò)展的,有一個(gè)靈活的模式氮兵,并且在Twitter中廣泛使用裂逐。然而,我們使這個(gè)組件可插拔泣栈。除了Cassandra之外卜高,Zipkin的存儲(chǔ)還支持ElasticSearch和MySQL。

要想把記錄的信息存儲(chǔ)到Mysqls南片,你需要在啟動(dòng)Zipkin Server的時(shí)候添加如下的參數(shù):

D:\>java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=10.10.10.10 --STORAGE_TYPE=mysql --MYSQL_DB=zipkin --MYSQL_HOST=10.10.1.10 --MYSQL_TCP_PORT=3306 --MYSQL_USER=root --MYSQL_PASS=123456

并且掺涛,要確保在zipkin庫下,已經(jīng)存在了需要用到的表疼进。建表語句需要與Zipkin Server的版本相對(duì)應(yīng)薪缆,避免未知錯(cuò)誤:

CREATETABLEIFNOTEXISTSzipkin_spans (

`trace_id_high`BIGINTNOTNULLDEFAULT0COMMENT'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',

`trace_id`BIGINTNOTNULL,

`id`BIGINTNOTNULL,

`name`VARCHAR(255)NOTNULL,

`remote_service_name`VARCHAR(255),

`parent_id`BIGINT,

`debug`BIT(1),

`start_ts`BIGINTCOMMENT'Span.timestamp(): epoch micros used for endTs query and to implement TTL',

`duration`BIGINTCOMMENT'Span.duration(): micros used for minDuration and maxDuration query',

PRIMARYKEY(`trace_id_high`,`trace_id`,`id`)

) ENGINE=InnoDB ROW_FORMAT=COMPRESSEDCHARACTERSET=utf8 COLLATE utf8_general_ci;

ALTERTABLEzipkin_spans ADD INDEX(`trace_id_high`,`trace_id`) COMMENT'for getTracesByIds';

ALTERTABLEzipkin_spans ADD INDEX(`name`) COMMENT'for getTraces and getSpanNames';

ALTERTABLEzipkin_spans ADD INDEX(`remote_service_name`) COMMENT'for getTraces and getRemoteServiceNames';

ALTERTABLEzipkin_spans ADD INDEX(`start_ts`) COMMENT'for getTraces ordering and range';

CREATETABLEIFNOTEXISTSzipkin_annotations (

`trace_id_high`BIGINTNOTNULLDEFAULT0COMMENT'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',

`trace_id`BIGINTNOTNULLCOMMENT'coincides with zipkin_spans.trace_id',

`span_id`BIGINTNOTNULLCOMMENT'coincides with zipkin_spans.id',

`a_key`VARCHAR(255)NOTNULLCOMMENT'BinaryAnnotation.key or Annotation.value if type == -1',

`a_value`BLOB COMMENT'BinaryAnnotation.value(), which must be smaller than 64KB',

`a_type`INTNOTNULLCOMMENT'BinaryAnnotation.type() or -1 if Annotation',

`a_timestamp`BIGINTCOMMENT'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',

`endpoint_ipv4`INTCOMMENT'Null when Binary/Annotation.endpoint is null',

`endpoint_ipv6`BINARY(16) COMMENT'Null when Binary/Annotation.endpoint is null, or no IPv6 address',

`endpoint_port`SMALLINTCOMMENT'Null when Binary/Annotation.endpoint is null',

`endpoint_service_name`VARCHAR(255) COMMENT'Null when Binary/Annotation.endpoint is null'

) ENGINE=InnoDB ROW_FORMAT=COMPRESSEDCHARACTERSET=utf8 COLLATE utf8_general_ci;

ALTERTABLEzipkin_annotations ADD UNIQUEKEY(`trace_id_high`,`trace_id`,`span_id`,`a_key`,`a_timestamp`) COMMENT'Ignore insert on duplicate';

ALTERTABLEzipkin_annotations ADD INDEX(`trace_id_high`,`trace_id`,`span_id`) COMMENT'for joining with zipkin_spans';

ALTERTABLEzipkin_annotations ADD INDEX(`trace_id_high`,`trace_id`) COMMENT'for getTraces/ByIds';

ALTERTABLEzipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT'for getTraces and getServiceNames';

ALTERTABLEzipkin_annotations ADD INDEX(`a_type`) COMMENT'for getTraces and autocomplete values';

ALTERTABLEzipkin_annotations ADD INDEX(`a_key`) COMMENT'for getTraces and autocomplete values';

ALTERTABLEzipkin_annotations ADD INDEX(`trace_id`,`span_id`,`a_key`) COMMENT'for dependencies job';

CREATETABLEIFNOTEXISTSzipkin_dependencies (

`day`DATENOTNULL,

`parent`VARCHAR(255)NOTNULL,

`child`VARCHAR(255)NOTNULL,

`call_count`BIGINT,

`error_count`BIGINT,

PRIMARYKEY(`day`,`parent`,`child`)

) ENGINE=InnoDB ROW_FORMAT=COMPRESSEDCHARACTERSET=utf8 COLLATE utf8_general_ci;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市伞广,隨后出現(xiàn)的幾起案子拣帽,更是在濱河造成了極大的恐慌,老刑警劉巖嚼锄,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诞外,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡灾票,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門茫虽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刊苍,“玉大人既们,你說我怎么就攤上這事≌玻” “怎么了啥纸?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長婴氮。 經(jīng)常有香客問我斯棒,道長,這世上最難降的妖魔是什么主经? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任荣暮,我火速辦了婚禮,結(jié)果婚禮上罩驻,老公的妹妹穿的比我還像新娘穗酥。我一直安慰自己,他們只是感情好惠遏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布砾跃。 她就那樣靜靜地躺著,像睡著了一般节吮。 火紅的嫁衣襯著肌膚如雪抽高。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天透绩,我揣著相機(jī)與錄音翘骂,去河邊找鬼。 笑死渺贤,一個(gè)胖子當(dāng)著我的面吹牛雏胃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播志鞍,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼瞭亮,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了固棚?” 一聲冷哼從身側(cè)響起统翩,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎此洲,沒想到半個(gè)月后厂汗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呜师,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年娶桦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衷畦,死狀恐怖栗涂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情祈争,我是刑警寧澤斤程,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站菩混,受9級(jí)特大地震影響忿墅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沮峡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一疚脐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帖烘,春花似錦亮曹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乡摹,卻和暖如春役耕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聪廉。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國打工瞬痘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人板熊。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓框全,卻偏偏與公主長得像,于是被迫代替她去往敵國和親干签。 傳聞我的和親對(duì)象是個(gè)殘疾皇子津辩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容