该文章介绍了IT行业采用链路调用工具的思路和实践,并针对分布式追踪系统的整合问题提出了OpenTracing的解决方案。文章还比较了几款常用的链路追踪工具,并介绍了CAT工具的部署和接入过程。最后,对CAT链路工具的应用进行了总结和理解。
在实践链路调用工具时,业界通常参考自Google于2010年发表的Dapper论文。该论文发布后,Twitter开发了一个名为Zipkin的链路调用工具,随后还有其他几款链路调用工具逐渐开源。尽管这些分布式追踪系统都有相似的API语法,但由于使用不同的语言和技术,各个系统的开发人员仍然很难将它们与特定的分布式追踪系统进行整合。因此,后来出现了一个名为Open Tracing的组织。Open Tracing通过提供平台无关、厂商无关的API,使开发人员能够轻松地添加或更换追踪系统的实现。 Open Tracing还提供了用于运营支持系统和针对特定平台的辅助程序库。有关程序库的详细信息,请参考相关规范。在学习链路调用工具之前,需要先了解一些链路追踪的术语定义。
Trace:一次分布式调用的链路追踪
Span:一个方法(局部或远程)调用踪迹
Annotation:附着在Span上的日志信息
Sampling:采样率
在这种系统中,每次链式调用都会为其生成一个唯一的追踪标识符(traceId)。当不同服务之间发生调用时,会为每个服务生成一个新的span标识符(spanId),其中上一个服务调用的spanId将作为当前服务调用的父标识符(parentId)。这种标识符的生成方式可以确保在复杂的服务调用链中,每个调用都能被准确地追踪和标识。
众多链路追踪工具中的大多数工具都基于Google Dapper的思路,其中包括Zipkin和Skywaking等。而还有一些工具并不采用Google Dapper的思路,例如CAT,它是参考了eBay CAL的思路而开发的。CAT是一款基于Java开发的实时应用监控平台,为美团点评提供全面的实时监控告警服务。以下是对一些广泛使用的链路追踪工具进行简单比较,优势点用红色字体标注。
此篇博客重点介绍CAT的使用,上面介绍了链路追踪的一些基本概念,接下来将重点介绍如何使用CAT完成链路追踪。要使用CAT首先需要部署CAT服务,部署CAT服务可以通过拉取源代码构建war包,也可以直接通过官网下载war包。CAT服务端部署步骤官网有详细的步骤,需要注意两个点,第一:官网提醒需要使用mysql5.6或者5.7,亲测过如果Mysql不使用5.x版本,CAT服务无法正常启动起来,本人在部署CAT服务时,使用的JDK是1.8,Mysql5.7,Tomcat8.x。另外,需要注意一个点,有些操作系统对根目录只有只读权限,在部署CAT服务端时,可以通过环境变量的方式修改CAT_HOME地址。在启动tomcat服务前,先执行如下脚本
export CAT_HOME=/data/appdatas/cat/
CATALINA_OPTS="$CATALINA_OPTS -server -DCAT_HOME=$CAT_HOME
以下是我自定义的CAT_HOME目录结构: - client.xml:位于CAT_HOME目录下,用于存放客户端配置文件。 - datasource.xml:位于CAT_HOME目录下,用于存放数据源配置文件。 - server.xml:位于CAT_HOME目录下,用于存放服务器配置文件。
在client.xml配置文件中,将server IP字段设置为本机的IP地址。由于CAT服务是单机本地部署而不是集群部署,所以只需填写本机的一个IP地址。
DataSource.xml中修改成本机安装的Mysql的用户名和密码即可,Server.xml文件内容如下所示:
当在Tomcat下启动服务时,我们可以监测CAT_HOME目录是否被正确地配置和生效,这将影响CAT服务是否能够成功启动。下面的示例显示了自定义目录已经成功生效。
启动过程中生成的日志文件保存在Tomcat的日志目录中,路径为tomcat/logs。通过访问http://localhost:8080来验证Tomcat是否已经成功启动。如果能够正常显示Tomcat的欢迎页面,则可以确认Tomcat已经成功启动。
一旦Tomcat成功启动,我们可通过访问CAT服务(http://localhost:8080/cat)来验证其可用性。如果CAT服务启动方面存在问题,可前往CAT_HOME/data/appdatas/cat 目录查看相应的启动日志,以便通过日志分析排除故障原因。此外,如果在Dashboard中能看到提示服务正常的信息,则可以确认CAT服务已成功部署,如下图所示:
在CAT服务中,您可以通过点击"Config"菜单来进行相关配置。如果您正在进行本机部署,您需要在客户端路由配置中将与IP地址相关的部分修改为本机的IP地址,并提交更改。
官网给出的服务端部署文档写的非常详细,对于本机单机部署而言,还是比较简单的,总结步骤如下所示:
- 安装的软件清单:JDK7或者JDK8,Mysql5.6或者Mysql5.7,Tomcat8.x
- 拉取源码生成war包或者从官网直接下载war包,下载3.1.0版本及以上的war包,war包放到tomcat的webapps目录下
- 创建/data/appdatas/cat目录,并修改datasource.xml,client.xml,server.xml,将文件放入目录
- 创建cat database,并初始化数据库数据,初始化脚本在源码中:script/CatApplication.sql
- 启动tomcat,登陆cat服务,查看cat服务是否成功启动
- 提交新的客户端路由信息
在前文中我们已经详细介绍了服务端的部署,现在我们将重点讨论客户端的接入方法。客户端接入非常简单,首先需要在客户端的pom.xml文件中添加cat-client的依赖项。
<dependency>
<groupId>com.dianping.cat</groupId>
<artifactId>cat-client</artifactId>
<version>${cat.version}</version>
</dependency>
在同级目录下的resources/META-INF/cat中,将client.xml文件放置于源代码中。在该文件中将服务器IP更改为所部署的CAT服务的机器IP地址,对于本机部署来说即为本机IP地址。在resources/META-INF目录下放置app.properties文件,文件内容为"app.name=应用名称"。client.xml文件的内容应如下所示:
作为一名IT工程师,需要注意的是,如果要自定义CAT_HOME目录,只有在服务端部署时才会生效。客户端的日志目录(/data/applogs/cat)是固定的,并且如果想要修改它,就需要修改客户端源代码,并生成新的jar包,然后引入项目中。所以,如果你只有对操作系统根目录的只读权限,你可以通过添加软链接的方式来解决这个问题。但是需要注意,这样可能会影响生成链路信息。以下是在Mac上创建软链接的步骤:
1.sudo vi /etc/synthetic.conf
2.进行文件映射 or 软连接,如:中间用Tab键隔开
data Users/taoli/data/applogs/cat
3.重启电脑
4.查看系统根目录就能看到data目录了
客户端集成的Demo地址,该Demo编写了四个服务,模拟服务间调用。依次启动服务,并访问最外层的UI服务,连续访问几次后,在CAT服务上查看生成的链路调用信息,服务调用关系如下:
通过CAT服务可以查看Transaction的信息,包括服务调用的响应时间、每秒的请求量(QPS)等。点击Log View可以查看服务间的详细调用关系,还能查看不同阶段的耗时信息。作为IT工程师,这些功能可以帮助我们更深入地分析和优化系统的性能。
Log View里面的链路信息如下所示,可以查看到服务之间调用关系以及每一步调用的耗时。
Problem报表可以查看发生异常的信息,例如错误的接口URL,错误量等信息。
点击Lg(SampleLinks)还可以查看到详细的报错信息,如下图所示:
更多关于报表的使用可以查看官网信息,除了监控信息查看,CAT还可以配置告警。CAT的一大优势也是支持丰富的报表信息。上面演示了CAT进行链路监控的效果,接下来分析Demo代码,从代码层面理解Java客户端如何与CAT集成。客户端集成都是以new transaction的方式完成,如下所示
Demo代码中先分析"acme-financial-ui"这个服务,这个服务中编写了CatServletFilter,这个Filter中把请求中的头信息读取出来,存放到catContext中,便于后面传递到下一个服务,这里编写Filter是假设还有其他服务会调用UI服务。
我除了编写了名为CatRestInterceptor的拦截器外,还实现了以下功能:该拦截器的目的是从catContext中获取信息,并将其放入请求的header中,向下一个服务传递。由于acme-financial-ui服务通过RestTemplate调用Back-office服务,而我添加了CatRestInterceptor拦截器,因此所有的RestTemplate调用都会附带添加的header信息。这样一来,服务之间的链路标识信息就会被传递下去。
下面是创建配置类,让CatServletFilter生效的代码。
下面是把CatRestInterceptor设置到RestTemplate对象上的代码。
back-office服务的代码和UI服务的代码相同,Account服务和Customer服务因为没有再调用其他服务,即没有用restTemplate调用其他服务,故这两个服务中只添加CatServletFilter即可,无需添加CatRestInterceptor即可,如下图所示。总结而言:埋点需要完成的核心实际就是把服务间的调用信息传递下去,传递方式是:通过servletFilter读取发送过来的请求的header信息,存入CatContext,调用下一个服务时,再从CatContext中读取信息存入request的header中传递下去。
为了更清晰的理解传递的链路信息,这里把Filter拦截存储的信息打印出来,整理如下。例如通过postman调用接口“http://localhost:8081/start”,也就是从UI这个服务发起服务调用。可以看到,因为UI服务没有被其他任何服务调用,所以Filter拦截到的信息都是null。另外,服务是由UI这个服务发起的,所以catContextRoot都是acme-financial-ui-c0a83209-461821-2015,对于back-office服务而言,Parent信息也是acme-financial-ui-c0a83209-461821-2015,并生成了child信息,传递给后面的Account和Customer服务,是Account和Customer服务的Parent信息。
在回到TraceId和SpanId的概念之前,需要指出acme-financial-ui-c0a83209-461821-2015是一个traceId,而各个服务会生成新的spanId,同时上一个服务的childId会成为下一个服务的parentId。当发起一个新的接口调用时,会生成新的TraceId信息。作为一名IT工程师,我们需要注意并理解这些概念的含义。
以上就是对CAT链路工具的学习和理解。
本文着重介绍了链路调用工具的应用和整合问题,并提到了几个常用的工具和解决方案。同时,通过CAT工具的部署和接入过程,给读者提供了详细的实践操作指导。文章内容比较全面,对于了解和学习链路追踪工具非常有帮助。