CAT實(shí)時(shí)監(jiān)控系統(tǒng):cat-client埋點(diǎn)設(shè)計(jì)

1.相關(guān)概念

如下在Cat中我們稱為: logview消息樹(或者M(jìn)essageTree),即應(yīng)用內(nèi)部的調(diào)用鏈路∠穹可參考:http://www.reibang.com/p/855207522411

圖1

2.整體設(shè)計(jì)介紹

Cat整體處理流程如下圖所示:
(cat-server對(duì)應(yīng)開源的cat-consumer模塊)

圖2

1. 業(yè)務(wù)接入cat-client倡蝙,進(jìn)行Cat埋點(diǎn)

2. cat-client將埋點(diǎn)信息,組織成logview消息樹踢步,上報(bào)到后端cat-sever服務(wù)器(通過tcp方式上報(bào))

3. cat-server端接受到logview癣亚,將logview放到不同的線程里進(jìn)行處理

3.1 Transaction線程,提取logview中transaction數(shù)據(jù)获印,構(gòu)造transaction報(bào)表述雾。

3.2 Event線程,提取logview中event數(shù)據(jù)兼丰,構(gòu)造event報(bào)表

3.3 Problem線程玻孟,提取logview中problem數(shù)據(jù),構(gòu)造problem報(bào)表

3.4 Logview線程鳍征,將logview進(jìn)行存儲(chǔ)黍翎。

4. 查詢端通過指定報(bào)表,查詢相應(yīng)數(shù)據(jù)艳丛。

3.logView樹構(gòu)造

logView樹(也叫 消息樹匣掸、messageTree):在同一個(gè)線程里,通過transaction容器氮双,將Cat產(chǎn)生的各個(gè)埋點(diǎn)進(jìn)行串聯(lián)碰酝,形成的進(jìn)程內(nèi)部的調(diào)用鏈路。

埋點(diǎn)示例一:

public void test() throws InterruptedException {
        Cat.initializeByDomain("cat.test");

        Transaction t1 = Cat.newTransaction("method", "test");
        try{
            test2("dpg");
        }catch (Exception e){
            Cat.logError(e);
            t1.setStatus(e); //設(shè)置transaction狀態(tài)
        }finally {
            t1.complete();   //transaction一定要complete戴差,一般放到finally來保證
        }
        
        //cat數(shù)據(jù)上報(bào)是異步的送爸,需要sleep一段時(shí)間等待數(shù)據(jù)上報(bào),在結(jié)束進(jìn)程
        Thread.sleep(3000);
 }
    
private void test2(String param) throws Exception {
        Cat.logEvent("test2param", param);

        Transaction t2 = Cat.newTransaction("method2", "test2");
        //中間執(zhí)行業(yè)務(wù)邏輯
        Thread.sleep(10);
        t2.setSuccessStatus();
        t2.complete();

        throw new Exception("error");
 }

生成的logView如下所示:

圖3

埋點(diǎn)示例二:

public void test() throws InterruptedException {
        Cat.initializeByDomain("cat.test");

        Transaction t1 = Cat.newTransaction("method", "test");
        try{
            test2("dpg");
        }catch (Exception e){
            Cat.logError(e);
            t1.setStatus(e); //設(shè)置transaction狀態(tài)
        }finally {
            t1.complete();   //transaction一定要complete,一般放到finally來保證
        }

        Transaction t3 = Cat.newTransaction("DbMethod", "DbTest");
        Cat.logEvent("db", "mysql");
        t3.complete();
        //cat數(shù)據(jù)上報(bào)是異步的袭厂,需要sleep一段時(shí)間等待數(shù)據(jù)上報(bào)墨吓,在結(jié)束進(jìn)程
        Thread.sleep(3000);
    }

    private void test2(String param) throws Exception {
        Cat.logEvent("test2param", param);

        Transaction t2 = Cat.newTransaction("method2", "test2");
        //中間執(zhí)行業(yè)務(wù)邏輯
        Thread.sleep(10);
        t2.setSuccessStatus();
        t2.complete();

        throw new Exception("error");
    }

會(huì)生成2個(gè)logView樹,如下圖所示:

圖4

圖5

4.原理解析

你的埋點(diǎn)會(huì)被cat-cliet 串街成一個(gè)logview消息樹纹磺,具體實(shí)現(xiàn)原理如下:

(t:代表transaction肛真, E:代表Event)(t:transaction開始,T:transaction結(jié)束)

圖6

1. 我們使用ThreadLocal變量爽航,當(dāng)new 一個(gè)Transaction1蚓让,會(huì)向stack push,并構(gòu)造 Logview 消息樹

2. Transaction2 new的時(shí)候讥珍,也會(huì)向stack push历极,并將Trasaction2 放到 當(dāng)前l(fā)ogView 消息樹中

3. Event new的時(shí)候,會(huì)將Event放到當(dāng)前l(fā)ogView消息樹中

4. Transaction2 complete衷佃,會(huì)從stack堆棧pop趟卸,并記錄transaction2的耗時(shí)時(shí)間、狀態(tài)氏义。

5. Transactin1 complete锄列,會(huì)從stack堆棧pop,并記錄transaction1的耗時(shí)時(shí)間惯悠、狀態(tài)邻邮。發(fā)現(xiàn)此時(shí)當(dāng)前stack為空,就會(huì)將當(dāng)前構(gòu)建好的Logview消息樹發(fā)送出去

6. 當(dāng)代碼流程在有Cat 埋點(diǎn)克婶,就會(huì)走上面同樣邏輯筒严。 (最頂層通過Transaction樹組織起來)

4.1 注意

1. Transaction一定要complete,并且不能跨線程comoplete(transaction的生成和complete需要在同一個(gè)線程里)

a. transaction只有complete我們才會(huì)發(fā)送整個(gè)logview消息樹情萤,如果你不complete鸭蛙,消息樹就不會(huì)發(fā)送,擠壓在內(nèi)存里筋岛,造成監(jiān)控?cái)?shù)據(jù)不準(zhǔn)娶视。進(jìn)而引發(fā)內(nèi)存泄漏風(fēng)險(xiǎn)。

b. 由于cat-client內(nèi)部使用ThreadLocal變量睁宰,所以需要在同一個(gè)線程進(jìn)行new 和complete肪获,否則complete會(huì)失效。

2. transaction complete順序勋陪,和new的順序相反贪磺。最先new的transaction,最后complete

a. transaction是一個(gè)堆棧結(jié)構(gòu)诅愚,需要complete 和new 相互對(duì)應(yīng)。

b. 如果,new的順序是 a b c违孝。 complete的順序 也是 a b c刹前。那么在complete a的時(shí)候,此時(shí)堆棧內(nèi)容是 c雌桑、b喇喉、a,

b1. 我們會(huì)從stack pop一個(gè)對(duì)象校坑,發(fā)現(xiàn)是c拣技,不是a本身,就會(huì)把c complete耍目。

b2. 繼續(xù)stack pop一個(gè)對(duì)象膏斤,發(fā)現(xiàn)是 b,不是a本身邪驮,就會(huì)把 b complete莫辨。

b3. 繼續(xù)stack pop 一個(gè)對(duì)象,發(fā)現(xiàn)是a本身毅访,就會(huì)把a(bǔ) complete

b4. 之后b沮榜、c complete,就不會(huì)產(chǎn)生任何動(dòng)作喻粹。

因?yàn)閎蟆融、c被提前complete,所以會(huì)導(dǎo)致耗時(shí)統(tǒng)計(jì)不準(zhǔn)守呜。

5. 采樣與聚合

1. 使用Cat埋點(diǎn)振愿,cat會(huì)在客戶端將埋點(diǎn)串成logview消息樹上報(bào)到cat后端,進(jìn)而解析成相應(yīng)報(bào)表弛饭。

2. 當(dāng)應(yīng)用流量變得很大冕末,埋點(diǎn)生成消息樹也會(huì)成爆發(fā)行增長(zhǎng),為了不影響客戶端機(jī)器性能侣颂,以及降低網(wǎng)絡(luò)流量档桃,我們會(huì)對(duì)cat埋點(diǎn)的消息樹,進(jìn)行采樣聚合憔晒。

采樣:只將部分logview 原樣上報(bào)藻肄,減少上報(bào)量。比如采樣率:1%拒担, 100個(gè)logview消息樹嘹屯,只會(huì)上報(bào)一個(gè)。

聚合:將未被采樣到的logview消息樹从撼,進(jìn)行聚合州弟、編碼變成一個(gè)消息樹 上報(bào),保證報(bào)表統(tǒng)計(jì)的準(zhǔn)確性。

如下圖所示婆翔,cat-client會(huì)將近3s未被采樣到的logview消息樹拯杠,聚合成一個(gè)消息樹。(被采樣到的logview會(huì)被原樣上報(bào))

在生成的新消息樹里啃奴,會(huì)統(tǒng)計(jì)每個(gè)transaction/event 次數(shù)潭陪、耗時(shí)。這樣就可以把很多l(xiāng)ogview 合并成一個(gè)logview最蕾,極大減少了網(wǎng)絡(luò)流量和消息量依溯。(多個(gè)logview被聚合成一個(gè)logview上報(bào),丟失了調(diào)用鏈路關(guān)系瘟则,但是指標(biāo)數(shù)量信息沒有丟失)

圖7

5.1 如何判斷一個(gè)鏈路是否被聚合

比如在Cat上查看一個(gè)鏈路黎炉,如下所示:

最頂層的埋點(diǎn)是System TransactionAggregator 或者 System EventAggregator 或則System _CatMergeTree(低版本) 則代表這個(gè)鏈路是被聚合的,不是真實(shí)的鏈路壹粟。 聚合的鏈路只是將:埋點(diǎn)的Transaction和Event 次數(shù)信息統(tǒng)計(jì)上報(bào)上來拜隧,為了保證Transaction、Event報(bào)表統(tǒng)計(jì)的準(zhǔn)確性趁仙,不代表真實(shí)的鏈路

圖8

5.2 如何查看被采樣到的鏈路

problem報(bào)表都是采樣到的鏈路洪添。對(duì)于耗時(shí)長(zhǎng)(比如耗時(shí)長(zhǎng)的rpc、db雀费、緩存調(diào)用)干奢、失敗的鏈路我們會(huì)在problem報(bào)表展示,所以在problem報(bào)表可以看到有問題的采樣鏈

6.截?cái)?/h1>

對(duì)于采樣命中的logview盏袄,我們會(huì)將整個(gè)logview發(fā)送到cat后端忿峻,進(jìn)行存儲(chǔ)。

對(duì)于有些業(yè)務(wù)辕羽,單個(gè)logview大小可能很多(比如:在一個(gè)循環(huán)里加了cat埋點(diǎn))逛尚,為了保證logview整個(gè)傳輸存儲(chǔ)的成功率,我們會(huì)對(duì)logview大小進(jìn)行限制刁愿。

如果發(fā)現(xiàn)logview埋點(diǎn)個(gè)數(shù)(Transaction+Event數(shù)量)超過2000绰寞,我們會(huì)將logview進(jìn)行截?cái)啵?000個(gè)大小作為限制進(jìn)行截?cái)唷?/p>

圖9

如果點(diǎn)擊logview如上圖所示铣口,有個(gè) RootLogview滤钱、ParentLogview的超鏈接,那么這個(gè)logview就是被截?cái)嗟摹?/p>

比如原始的logview脑题,因?yàn)檫^長(zhǎng)被截成5段件缸。

其中:RootLogview:鏈接到第一段logview

ParentLogview:連接到上一個(gè)被截?cái)嗪蟮膌ogview

6.1 截?cái)嘣?/strong>

圖10

a. 如上圖所示,當(dāng)前我們處于1這個(gè)階段叔遂,此時(shí)內(nèi)存構(gòu)造的logview樹狀態(tài)是A(其中他炊,t:代表 開始一個(gè)Transaction争剿,T:代表結(jié)束一個(gè)Transaction,E:代表一個(gè)Event或者Error)

b. 當(dāng)我們繼續(xù)new 一個(gè)Transctioin t7時(shí)佑稠,會(huì)檢查當(dāng)前內(nèi)存中l(wèi)ogview的長(zhǎng)度秒梅,如果長(zhǎng)度超過2000限制(即:Transaction + Event + Error 數(shù)量)旗芬,開始對(duì)logview進(jìn)行截?cái)嗌嘟海M(jìn)入階段2

c. 在階段2,我們會(huì)把已經(jīng)complete的Transaction(t3疮丛、t4)打包在一起幔嫂,構(gòu)造一個(gè)新的完整logview A1 發(fā)送(當(dāng)然發(fā)送是異步,不會(huì)阻塞進(jìn)程)

d. 沒有complete的Transaction(t1誊薄、t2履恩、t5、t6)會(huì)再次組裝在一起呢蔫,變成A2切心,繼續(xù)留在內(nèi)存里 ,這樣當(dāng)new Transaction t7片吊,t7被加入到A2中绽昏,進(jìn)入到階段3,繼續(xù)等待新的埋點(diǎn)數(shù)據(jù)加入

e. 直到整個(gè)t1 這個(gè)transaction complete俏脊,整個(gè)logview才會(huì)發(fā)送走

6.2 截?cái)鄦栴}

a. 統(tǒng)計(jì)次數(shù)不準(zhǔn):根據(jù)上面所述全谤,在截?cái)鄷r(shí), t1爷贫、t2认然、t5、t6 其實(shí)統(tǒng)計(jì)數(shù)據(jù)會(huì)不準(zhǔn)漫萄。因?yàn)樵贏1中發(fā)送過一次卷员,在A2中還會(huì)發(fā)送一次(當(dāng)然截?cái)啻螖?shù)越多,統(tǒng)計(jì)數(shù)值偏差越大)腾务。不過為了修復(fù)統(tǒng)計(jì)次數(shù)不準(zhǔn)毕骡,我們不會(huì)統(tǒng)計(jì)t1次數(shù),知道最后一次階段上報(bào)才會(huì)統(tǒng)計(jì)t1窑睁,其實(shí)這么做也只是解決了t1統(tǒng)計(jì)不準(zhǔn)確問題挺峡。具體為什么不修復(fù)其他transaction統(tǒng)計(jì)不準(zhǔn)問題,只能說太復(fù)雜担钮,不好搞

b. 耗時(shí)統(tǒng)計(jì)不準(zhǔn):被階段后橱赠,同一個(gè)transaction被放到2個(gè)logview里了(比如t2),這樣耗時(shí)就被拆分成2部分箫津,所以平均耗時(shí)狭姨,會(huì)偏低

6.3 截?cái)鄷r(shí)機(jī):

1. transaction+event+error數(shù)量超過 2000

2. logview 跨小時(shí)超過10s

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宰啦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子饼拍,更是在濱河造成了極大的恐慌赡模,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件师抄,死亡現(xiàn)場(chǎng)離奇詭異漓柑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)叨吮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門辆布,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人茶鉴,你說我怎么就攤上這事锋玲。” “怎么了涵叮?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵惭蹂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我割粮,道長(zhǎng)盾碗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任穆刻,我火速辦了婚禮置尔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘氢伟。我一直安慰自己榜轿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布朵锣。 她就那樣靜靜地躺著谬盐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诚些。 梳的紋絲不亂的頭發(fā)上飞傀,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音诬烹,去河邊找鬼砸烦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绞吁,可吹牛的內(nèi)容都是我干的幢痘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼家破,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼颜说!你這毒婦竟也來了购岗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤门粪,失蹤者是張志新(化名)和其女友劉穎喊积,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玄妈,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乾吻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了措近。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溶弟。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡女淑,死狀恐怖瞭郑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸭你,我是刑警寧澤屈张,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站袱巨,受9級(jí)特大地震影響阁谆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜愉老,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一场绿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嫉入,春花似錦焰盗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至垫竞,卻和暖如春澎粟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欢瞪。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工活烙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人遣鼓。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓啸盏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親譬正。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宫补,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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