CAT实时监控系统:cat-client埋点设计

1.相关概念

如下在Cat中我们称为: logview消息树(或者MessageTree),即应用内部的调用链路。可参考:https://www.jianshu.com/p/855207522411

图1

2.整体设计介绍

Cat整体处理流程如下图所示:
(cat-server对应开源的cat-consumer模块)

图2

1. 业务接入cat-client,进行Cat埋点

2. cat-client将埋点信息,组织成logview消息树,上报到后端cat-sever服务器(通过tcp方式上报)

3. cat-server端接受到logview,将logview放到不同的线程里进行处理

3.1 Transaction线程,提取logview中transaction数据,构造transaction报表。

3.2 Event线程,提取logview中event数据,构造event报表

3.3 Problem线程,提取logview中problem数据,构造problem报表

3.4 Logview线程,将logview进行存储。

4. 查询端通过指定报表,查询相应数据。

3.logView树构造

logView树(也叫 消息树、messageTree):在同一个线程里,通过transaction容器,将Cat产生的各个埋点进行串联,形成的进程内部的调用链路。

埋点示例一:

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); //设置transaction状态
        }finally {
            t1.complete();   //transaction一定要complete,一般放到finally来保证
        }
        
        //cat数据上报是异步的,需要sleep一段时间等待数据上报,在结束进程
        Thread.sleep(3000);
 }
    
private void test2(String param) throws Exception {
        Cat.logEvent("test2param", param);

        Transaction t2 = Cat.newTransaction("method2", "test2");
        //中间执行业务逻辑
        Thread.sleep(10);
        t2.setSuccessStatus();
        t2.complete();

        throw new Exception("error");
 }

生成的logView如下所示:

图3

埋点示例二:

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); //设置transaction状态
        }finally {
            t1.complete();   //transaction一定要complete,一般放到finally来保证
        }

        Transaction t3 = Cat.newTransaction("DbMethod", "DbTest");
        Cat.logEvent("db", "mysql");
        t3.complete();
        //cat数据上报是异步的,需要sleep一段时间等待数据上报,在结束进程
        Thread.sleep(3000);
    }

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

        Transaction t2 = Cat.newTransaction("method2", "test2");
        //中间执行业务逻辑
        Thread.sleep(10);
        t2.setSuccessStatus();
        t2.complete();

        throw new Exception("error");
    }

会生成2个logView树,如下图所示:

图4

图5

4.原理解析

你的埋点会被cat-cliet 串街成一个logview消息树,具体实现原理如下:

(t:代表transaction, E:代表Event)(t:transaction开始,T:transaction结束)

图6

1. 我们使用ThreadLocal变量,当new 一个Transaction1,会向stack push,并构造 Logview 消息树

2. Transaction2 new的时候,也会向stack push,并将Trasaction2 放到 当前logView 消息树中

3. Event new的时候,会将Event放到当前logView消息树中

4. Transaction2 complete,会从stack堆栈pop,并记录transaction2的耗时时间、状态。

5. Transactin1 complete,会从stack堆栈pop,并记录transaction1的耗时时间、状态。发现此时当前stack为空,就会将当前构建好的Logview消息树发送出去

6. 当代码流程在有Cat 埋点,就会走上面同样逻辑。 (最顶层通过Transaction树组织起来)

4.1 注意

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

a. transaction只有complete我们才会发送整个logview消息树,如果你不complete,消息树就不会发送,挤压在内存里,造成监控数据不准。进而引发内存泄漏风险。

b. 由于cat-client内部使用ThreadLocal变量,所以需要在同一个线程进行new 和complete,否则complete会失效。

2. transaction complete顺序,和new的顺序相反。最先new的transaction,最后complete

a. transaction是一个堆栈结构,需要complete 和new 相互对应。

b. 如果,new的顺序是 a b c。 complete的顺序 也是 a b c。那么在complete a的时候,此时堆栈内容是 c、b、a,

b1. 我们会从stack pop一个对象,发现是c,不是a本身,就会把c complete。

b2. 继续stack pop一个对象,发现是 b,不是a本身,就会把 b complete。

b3. 继续stack pop 一个对象,发现是a本身,就会把a complete

b4. 之后b、c complete,就不会产生任何动作。

因为b、c被提前complete,所以会导致耗时统计不准。

5. 采样与聚合

1. 使用Cat埋点,cat会在客户端将埋点串成logview消息树上报到cat后端,进而解析成相应报表。

2. 当应用流量变得很大,埋点生成消息树也会成爆发行增长,为了不影响客户端机器性能,以及降低网络流量,我们会对cat埋点的消息树,进行采样聚合。

采样:只将部分logview 原样上报,减少上报量。比如采样率:1%, 100个logview消息树,只会上报一个。

聚合:将未被采样到的logview消息树,进行聚合、编码变成一个消息树 上报,保证报表统计的准确性。

如下图所示,cat-client会将近3s未被采样到的logview消息树,聚合成一个消息树。(被采样到的logview会被原样上报)

在生成的新消息树里,会统计每个transaction/event 次数、耗时。这样就可以把很多logview 合并成一个logview,极大减少了网络流量和消息量。(多个logview被聚合成一个logview上报,丢失了调用链路关系,但是指标数量信息没有丢失)

图7

5.1 如何判断一个链路是否被聚合

比如在Cat上查看一个链路,如下所示:

最顶层的埋点是System TransactionAggregator 或者 System EventAggregator 或则System _CatMergeTree(低版本) 则代表这个链路是被聚合的,不是真实的链路。 聚合的链路只是将:埋点的Transaction和Event 次数信息统计上报上来,为了保证Transaction、Event报表统计的准确性,不代表真实的链路

图8

5.2 如何查看被采样到的链路

problem报表都是采样到的链路。对于耗时长(比如耗时长的rpc、db、缓存调用)、失败的链路我们会在problem报表展示,所以在problem报表可以看到有问题的采样链

6.截断

对于采样命中的logview,我们会将整个logview发送到cat后端,进行存储。

对于有些业务,单个logview大小可能很多(比如:在一个循环里加了cat埋点),为了保证logview整个传输存储的成功率,我们会对logview大小进行限制。

如果发现logview埋点个数(Transaction+Event数量)超过2000,我们会将logview进行截断,以2000个大小作为限制进行截断。

图9

如果点击logview如上图所示,有个 RootLogview、ParentLogview的超链接,那么这个logview就是被截断的。

比如原始的logview,因为过长被截成5段。

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

ParentLogview:连接到上一个被截断后的logview

6.1 截断原理

图10

a. 如上图所示,当前我们处于1这个阶段,此时内存构造的logview树状态是A(其中,t:代表 开始一个Transaction,T:代表结束一个Transaction,E:代表一个Event或者Error)

b. 当我们继续new 一个Transctioin t7时,会检查当前内存中logview的长度,如果长度超过2000限制(即:Transaction + Event + Error 数量),开始对logview进行截断,进入阶段2

c. 在阶段2,我们会把已经complete的Transaction(t3、t4)打包在一起,构造一个新的完整logview A1 发送(当然发送是异步,不会阻塞进程)

d. 没有complete的Transaction(t1、t2、t5、t6)会再次组装在一起,变成A2,继续留在内存里 ,这样当new Transaction t7,t7被加入到A2中,进入到阶段3,继续等待新的埋点数据加入

e. 直到整个t1 这个transaction complete,整个logview才会发送走

6.2 截断问题

a. 统计次数不准:根据上面所述,在截断时, t1、t2、t5、t6 其实统计数据会不准。因为在A1中发送过一次,在A2中还会发送一次(当然截断次数越多,统计数值偏差越大)。不过为了修复统计次数不准,我们不会统计t1次数,知道最后一次阶段上报才会统计t1,其实这么做也只是解决了t1统计不准确问题。具体为什么不修复其他transaction统计不准问题,只能说太复杂,不好搞

b. 耗时统计不准:被阶段后,同一个transaction被放到2个logview里了(比如t2),这样耗时就被拆分成2部分,所以平均耗时,会偏低

6.3 截断时机:

1. transaction+event+error数量超过 2000

2. logview 跨小时超过10s

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容