谁说Cat不能做链路跟踪的,给我站出来
背景
链路跟踪,我们有很多可选项。常见的有 zipkin,pinpoint,skywalking,jaeger 等。
基本上都是根据谷歌的《Dapper 大规模分布式系统的跟踪系统》这篇论文发展出来的。
今天讲下 Cat 里的链路跟踪要如何来实现,没用过 Cat 的同学可以查看我的这篇文章 《熬夜之作:一文带你了解 Cat 分布式监控》进行了解。
在 Cat 中可以很方便的看到每个请求的总耗时以及业务操作,数据库操作的耗时情况。对于服务之间的调用也可以通过埋点的方式进行监控。
如下图,可以看出请求内发起了一次 RPC 的调用,callRPC 开头的那条记录。耗时 11ms, 但是这个 RPC 服务内部耗时花在哪里了,在这边不能直接查看,只能去另一个服务中查看,不是很方便。
详细的我画了一张图说明下现在的问题:
从上图可以看出,一个请求经过了多个服务,每个服务中对远程调用或者本地调用都有埋点,这样就能监控到调用的异常和性能指标。
下面一部分是在 Cat 中我们去查看这些指标的场景,Cat 中的数据展示是以项目维度来展示的,所以每个服务都有自己的监控数据。
如果我想要知道刚刚那次请求,在整个链路中哪里最慢,耗时在哪里,我得分别去 4 个服务下面才能看到这些信息,不直观。
实现方式
如下图所示:
从网关到服务,从服务到服务,都需要将 Trace 信息进行传递才可以将整个链路串起来。只有串起来了才可以在 Cat 中查看到整个链路的耗时信息。
本文需要实现的效果就是可以在请求的入口处(网关),查看到这个请求经过的所有服务,每个服务中的耗时情况。
要想将整个请求都串连起来,必须要有一个唯一的请求标识,一般我们称之为 traceId。剩余的工作就是将链路相关的信息层层传递下去。
首先在每个服务的过滤器中进行请求头信息的接收,比如从网关到服务 A,那么服务 A 需要接收这些信息然后传递给下一个服务。
HTTP 请求的消息树构建:
// 构建远程消息树
if(request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_ROOT_MESSAGE_ID) != null){
CatContext catContext = new CatContext();
catContext.addProperty(Cat.Context.ROOT,request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_ROOT_MESSAGE_ID));
catContext.addProperty(Cat.Context.PARENT,request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_PARENT_MESSAGE_ID));
catContext.addProperty(Cat.Context.CHILD,request.getHeader(CatConstantsExt.CAT_HTTP_HEADER_CHILD_MESSAGE_ID));
Cat.logRemoteCallServer(catContext);
}
将消息树的信息传递给下个服务的话就要看你用的调用方式是什么,如果用 Feign 或者 RestTemplate 都可以利用拦截器来实现传递。
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
CatContext catContext = new CatContext();
Cat.logRemoteCallClient(catContext,Cat.getManager().getDomain());
template.header(CatConstantsExt.CAT_HTTP_HEADER_ROOT_MESSAGE_ID, catContext.getProperty(Cat.Context.ROOT));
template.header(CatConstantsExt.CAT_HTTP_HEADER_PARENT_MESSAGE_ID, catContext.getProperty(Cat.Context.PARENT));
template.header(CatConstantsExt.CAT_HTTP_HEADER_CHILD_MESSAGE_ID, catContext.getProperty(Cat.Context.CHILD));
}
}
如果用的是 Dubbo 的话可以用 Dubbo 的 Filter 来实现相同的效果。
最终的效果如下图,调用了 articles/newest 接口,网关将请求转发到 article-provider 服务,article-provider 中又调用了 user-provider 的 users/uid 接口获取用户信息,最重要的是 user-provider 中有哪些操作的耗时在这里也能直观的看到,非常方便。
完整源码参考:https://github.com/yinjihuan/kitty[1]
关于作者 :尹吉欢,简单的技术爱好者,《Spring Cloud 微服务-全栈技术与案例解析》, 《Spring Cloud 微服务 入门 实战与进阶》作者, 公众号 猿天地 发起人。个人微信 jihuan900 ,欢迎勾搭。
参考资料
kitty: https://github.com/yinjihuan/kitty
往期推荐
后台回复 学习资料 领取学习视频
如有收获,点个在看,诚挚感谢
本文分享自微信公众号 - 猿天地(cxytiandi)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
同时搞定Android和iOS的Dart语言(1):Dart初探
用Flutter开发Android App和iOS App需要使用Dart语言,所以本系列文章会深入介绍Dart语言的相关知识,后续还会推出Flutter App开发的系列文章,敬请期待! 1 Dart简介 Dart诞生于2011年10月10日,谷歌Dart语言项目负责人Lars Bak在丹麦举行的Goto会议上宣布,Dart是一种“结构化的Web编程语言”,Dart编程语言在所有现代浏览器和环境中高效地运行。 尽管Dart是Google开发的计算机编程语言,但后来被ECMA认定为标准。这门语言可以用于Web、服务器、移动应用和物联网等领域开发,是宽松开源许可证(经过修改的BSD证书)下的开源软件。 目前Dart的最新版是Dart2,Dart2是一款高效、简洁、已通过大量实战检验的编程语言,可以应对现代应用程序开发的挑战。Dart2对类型系统进行了精简,清理了语法,并重建了大部分开发工具链,使得开发移动和Web引用变得更加高效。 那么为什么Flutter团队选择了Dart呢?其实Flutter在最开始评估了十多种语言,最终才选择Dart,因为Dart非常符合构建用户界面的方式。下面是D...
- 下一篇
同时搞定Android和iOS的Dart语言(2):变量与常量
1. 定义和使用变量 尽管Dart是静态语言,但仍然拥有动态特性。所以定义变量也有如下2种方式。 使用数据类型定义变量 使用var定义变量 在Dart语言中,数据类型放在变量前面,格式如下: 数据类型 变量名; 在Dart语言中,每条语句后面必须跟分号(;),所以在定义变量时后面也要加分号。如下面的代码定义了一个整数类型的变量和一个字符串类型的变量。 int num; // 整数类型的变量String s; // 字符串类型的变量 在定义变量时可以同时为变量赋值,也称为初始化,所以可以用下面的代码为num和s赋值。 int num = 20;String s = "hello world"; 如果在定义变量时指定了数据类型,那么就意味着变量的数据类型不可以改变,例如,上面代码中已经将num变量定义为int类型,那么num就永远是int类型,不可以为该变量赋其他类型的值。 由于Dart语言中一切皆为对象,所以如果在定义变量时没有为其初始化,那么变量的默认值就是null。 另外一种定义变量的方法是使用var关键字,代码如下: var num = 20; // num被自动识别为int类型...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- 设置Eclipse缩进为4个空格,增强代码规范