文末,本文转载自微信公众号“码猿技术专栏”,作者为陈谋。转载本文请联系码猿科技专栏公众号。在今天的文章中,陈老师介绍了链接跟踪相关的知识,重点介绍了SpringCloudSleuth和zipkin这两个组件,后续文章再介绍一个。文章内容如下:为什么需要链接跟踪?在一个大规模的分布式微服务系统中,一个系统被拆分成N个模块。这些模块负责不同的功能,组合成一个系统,最终可以提供丰富的功能。在这种分布式架构中,一个请求往往需要涉及多个服务,如下图:服务之间的调用错综复杂,维护成本成倍增加。必然会出现以下问题:如何看清依赖关系?发生异常时如何快速定位异常服务?当出现性能瓶颈时,如何快速定位受影响的服务?为了快速定位分布式架构中的问题,分布式链路跟踪应运而生。将分布式请求恢复到调用链路,进行日志记录,性能监控,集中展示分布式请求的调用状态。比如每个服务节点上的耗时,请求到达的机器,每个服务节点的请求状态等等。常见的链接跟踪技术有哪些?市面上链接跟踪项目很多,其中一些比较优秀,如下:cat:大众点评开源,基于Java开发的应用实时监控平台,包括应用实时监控、业务监控。集成方案是通过代码埋点来实现监控,比如:拦截器、过滤器等,对代码的侵入性很大,集成成本高,风险大。Zipkin:由Twitter开源,一个开源的分布式跟踪系统,用于采集服务的时序数据,解决微服务架构中的延迟问题,包括:数据采集、存储、搜索和展示。这个产品结合spring-cloud-sleuth使用起来比较简单,集成也很方便,但是功能比较单一。pinpoint:韩国开源基于字节码注入的调用链分析和应用监控分析工具。特点是支持多种插件,UI功能强大,接入端无代码入侵。特点是支持多种插件,UI功能强大,接入端无代码入侵。目前加入了Apache孵化器。Sleuth:SpringCloud提供的分布式系统中的链接跟踪解决方案。比较遗憾的是,阿里巴巴系目前还没有链接跟踪相关的开源项目。我们可以使用SpringCloudSleuth+Zipkin作为链接跟踪方案。什么是SpringCloudSleuth?SpringCloudSleuth实现了一个分布式服务链接跟踪方案。通过使用Sleuth,我们可以快速定位服务问题。简单来说,Sleuth相当于调用链监控工具的客户端,集成在各个微服务上,负责生成调用链监控数据。SpringCloudSleuth只负责生成监控数据,以日志的形式展示,不提供可视化的UI界面。在学习Sleuth之前,你必须了解它的几个概念:Span:基本工作单元,相当于链表中的一个节点,它的开始、具体过程和结束都用唯一的ID来标记。我们可以通过其中存储的开始和结束时间戳来统计服务调用的耗时。此外,还可以获取事件的名称、请求信息等。Trace:由一系列Span系列组成的树状结构。当请求到达系统入口时,会创建一个唯一ID(traceId)来唯一标识一个链接。这个traceId一直在服务之间传递,直到请求返回,然后你就可以用这个traceId来串联整个请求,形成一个完整的链接。注解:一些核心注解用于标记微服务调用之间的事件。重要注解如下:cs(ClientSend):客户端发送请求,开始一个请求生命周期sr(ServerReceived):服务器接受请求并处理;sr-cs=networkdelay=servicecalltimess(ServerSend):服务端处理后准备发送给客户端;ss-sr=服务器上的请求处理时间cr(ClientReveived):客户端收到服务器的响应,请求结束;cr-sr=请求的总时间SpringCloud是如何集成Sleuth的?集成SpringCloudSleuth并不难。在此之前,需要准备以下三个服务:gateway-sleuth9031:作为网关服务sleuth-product9032:商品微服务sleuth-order9033:订单微服务三个服务的调用关系如下:客户端请求网关发起订单查询请求,网关路由到订单服务,订单服务获取订单详情,调用商品服务获取商品详情。添加依赖在父模块中添加sleuth依赖,如下:SpringCloudSleuth的依赖,还有Nacos和openFeign的依赖,这里就不赘述了。有什么不懂的,可以借助陈老师之前的文章和案例源码来补漏。调整日志级别由于sleuth没有UI界面,需要调整日志级别才能在控制台看到更详细的链接信息。在三个服务的配置文件中添加如下配置:##设置openFeign和sleuth的日志级别为debug,方便查看日志信息logging:level:org.springframework.cloud.openfeign:debugorg.springframework.cloud.sleuth:debugdemo界面改进以下界面仅用于演示创建的数据,不集成DB。sleuth-order9033查询订单详情界面如下图:sleuth-product9032查询商品详情界面如下图:gateway-sleuth9031网关路由配置如下:teststartthe以上三个服务,直接浏览器访问:http://localhost:9031/order/get/12观察控制台日志输出,如下图所示:日志格式有四个参数,含义如下如下:第一个:服务名称第二个:traceId,唯一标识一个链接第三个:spanId,链接中的基本工作单元idservicesforobservation,这里没有集成zipkin,所以是假的,既然集成完成了,不由得倒吸一口凉气。直接看日志不是瞎子。什么是ZipKin?Zipkin是Twitter的一个开源项目,基于GoogleDapper实现,致力于收集服务的时序数据,解决微服务架构中的延迟问题,包括数据的收集、存储、搜索和展示。ZipKin的基本结构如下图所示:Zipkin分为四个核心组件,如下:Collector:收集器组件,主要用于处理从外部系统发来的跟踪信息,并将这些信息转换成Span格式处理内部采用Zipkin,支持后续的存储、分析、展示等功能。Storage:存储组件,主要处理采集器收到的跟踪信息。默认情况下,此信息存储在内存中。我们还可以修改这种存储策略,通过使用其他存储组件将跟踪信息存储在数据库中。RESTfulAPI:API组件,主要用于对外提供访问接口。例如向客户端显示跟踪信息,或者连接外部系统访问进行监控等。UI:基于API组件实现的上层应用。通过UI组件,用户可以方便、直观地查询和分析跟踪信息。Zipkin分为服务端和客户端。服务器主要用于收集和显示跟踪数据。客户端的主要功能是发送给服务器。微服务应用也是客户端,这样一旦调用发生,就会触发监听器将sleuth日志数据传输到服务端。如何搭建zipkin服务器?首先需要下载服务器的jar包,地址:https://search.maven.org/artifact/io.zipkin/zipkin-server/2.23.4/jar下载后会得到一个jar包。如下图:直接启动jar,命令如下:java-jarzipkin-server-2.23.4-exec.jar出现如下界面表示启动完成:此时可以访问zipkin的UI界面,地址:http://localhost:9411,界面如下:以上是通过下载jar搭建服务器,当然还有其他方式安装,比如docker,试试吧自己,陈不会再证明了。如何构建zipKin客户端?服务器只是跟踪数据的采集和展示,客户端是数据的生成和传输端。下面详细介绍如何搭建客户端。还是上面例子中的三个微服务,直接添加zipkin依赖,如下:>spring-cloud-starter-zipkin注意:由于spring-cloud-starter-zipkin已经包含了SpringCloudSleuth的依赖,所以只需要引入上述依赖即可。配置文件需要配置zipkin服务器的地址。配置如下:spring:cloud:sleuth:sampler:#日志数据采样百分比,默认0.1(10%),这里为了测试设置为100%,生产环境只需要0.1probability:1.0zipkin:#zipkinserver的请求地址base-url:http://127.0.0.1:9411#让nacos把它当作一个URL而不是一个服务名discovery-client-enabled:false上面的配置完成后启动服务就对了,此时访问:http://localhost:9031/order/get/12调用接口后,再次访问zipkin的UI界面,如下图:可以看到刚刚调用的接口已经被监听,点击SHOW进入详情视图,如下图:可以看到左边展示了一个完整的链接,包括服务名称,耗时,右边展示了服务调用的信息,包括开始,结束时间,请求url,请求方法.....exceptcall为t的相关信息链接,也可以清楚的看到各个服务的依赖关系如下图,如下图:如何切换zipKin的数据传输方式?zipkin默认的传输方式是HTTP,但是这里有个问题。一旦客户端在传输过程中服务器断开连接,这个跟踪日志信息就会丢失。当然zipkin也支持MQ传输,支持消息中间件如下:ActiveMQRabbitMQKafka使用MQ传输不仅可以保证消息丢失的问题,还可以提高传输效率。生产中推荐使用MQ传输。那么问题来了,如何切换?其实方法很简单。让陈以RabbitMQ为例来介绍一下。1、服务器连接RabbitMQ运行服务器,连接RabbitMQ。命令如下:java-jarzipkin-server-2.23.4-exec.jar--zipkin.collector.rabbitmq.addresses=localhost--zipkin.collector.rabbitmq.username=guest--zipkin.collector.rabbitmq.password=guest命令解析如下:zipkin.collector.rabbitmq.addresses:MQ地址zipkin.collector.rabbitmq.username:用户名zipkin.collector.rabbitmq.password:密码2、客户端添加由于RabbitMQ使用MQ传输,必须添加相应的依赖和配置。添加RabbitMQ依赖如下:如下:spring:rabbitmq:addresses:127.0.0.1username:guestpassword:guest3,在配置文件spring.cloud.zipkin.sender.type中切换传输模式,这个配置是用来切换传输模式的,rabbit的值表示使用rabbitMQ进行数据传输。配置如下:spring:cloud:zipkin:sender:##使用rabbitMQ进行数据传输type:rabbit注意:如果使用MQ传输,可以去掉spring.cloud.zipkin.sender.base-url。完整的配置如下图所示:4.由于测试使用的是MQ传输,所以我们可以在不启动服务器的情况下成功传输。浏览器访问:http://localhost:9031/order/get/12此时发现服务并没有报异常,查看RabbitMQ,数据已经传输完毕,存在于zipkin队列中,如如下图所示:可以看到有消息没有被消费,可以看到消息的内容是Trace和Span的相关信息。好的,让我们使用以下命令启动服务器:java-jarzipkin-server-2.23.4-exec.jar--zipkin.collector.rabbitmq.addresses=localhost--zipkin.collector.rabbitmq.username=guest--zipkin。collector.rabbitmq.password=guestserver启动后,发现zipkin队列中的消息被瞬间消费。查看zipkin的UI界面,发现链接信息已经生成,如下图:zipkin如何持久化?zipkin信息默认保存在内存中,一旦服务器重启这些信息就会丢失,但是zipkin提供了可插拔存储。Zipkin支持以下四种存储方式:内存:服务重启会失败,不推荐使用MySQL:数据量越大,性能越差Elasticsearch:主流方案,推荐使用Cassandra:技术太好了,用的人少it,自己选择,不过官方推荐的是,今天小陈就以MySQL为例,介绍一下zipkin是如何持久化的。Elasticsearch放在下一篇,有点长。1、创建数据库zipkinserver上的MySQL建表SQL在源码中的zipkin-storage/mysql-v1/src/main/resources/mysql.sql中。我将把这个SQL文件放在案例源代码中。github地址:https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql创建数据库:zipkin(任意名称),导入建表SQL,新建的数据库表如下图:2.服务器配置MySQL服务器配置很简单,运行如下命令:java-jarzipkin-server-2.23.4-exec.jar--STORAGE_TYPE=mysql--MYSQL_HOST=127.0.0.1--MYSQL_TCP_PORT=3306--MYSQL_DB=zipkin--MYSQL_USER=root--MYSQL_PASS=Nov2014以上命令的参数分析如下:STORAGE_TYPE:指定存储方式,默认内存格式MYSQL_HOST:MySQLip地址,默认localhostMYSQL_TCP_PORT:MySQL端口号,默认端口3306MYSQL_DB:MySQL中的数据库名称,默认为zipkinMYSQL_USER:用户名MYSQL_PASS:密码Chen是怎么记住这些参数的?废话,肯定记不住,随时查看源码,这些配置都在源码的配置文件/zipkin-server/src/main/resources/zipkin-server-shared.yml中,比如上面提到的MySQL相关配置,如下图所示:zipkinserver的所有配置项都在这里,没事可以翻翻看。github地址:https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml然后使用rabbitMQ传输方式,MySQL持久化方式,完整命令如下:java-jarzipkin-server-2.23.4-exec.jar--STORAGE_TYPE=mysql--MYSQL_HOST=127.0.0.1--MYSQL_TCP_PORT=3306--MYSQL_DB=zipkin--MYSQL_USER=root--MYSQL_PASS=Nov2014--zipkin。collector.rabbitmq.addresses=localhost--zipkin.collector.rabbitmq.username=guest--zipkin.collector.rabbitmq.password=guest持久化是服务器做的事情,和客户端没有关系,所以这是结束了,小陈就不再测试了,自己试试看。总结前面介绍了这么多,不知道大家有没有仔细看,陈总总结一下:SpringCloudSleuth作为链路追踪的一个组件,只提供了日志收集和日志打印功能,并没有可视化UIZipkin接口提供了强大的日志跟踪分析、可视化、服务依赖分析等相关功能。结合SpringCloudSleuth作为主流方案,zipkin推荐生产环境切换MQ传输方式。这有两个好处,可以防止数据丢失。MQ为异步解耦,极大的提升了性能。Zipkin默认是以内存的形式存储的。MySQL虽然也是一种方法,但是随着数据量的增加,性能会变差。因此生产环境推荐使用Elasticsearch,下篇文章会介绍。
