文章目录
前言
本章代码已分享至Gitee: https://gitee.com/lengcz/springcloudalibaba01.git
在大型系统的微服务架构中,一个系统被拆分成很多模块。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。在这种架构中,一次请求往往涉及多个服务。互联网应用架构在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能分布在几千台服务器上,横跨多个不同的数据中心,也就意味着这种架构形式也会存在一些问题。
- 如何快速发现问题?
- 如何判断故障影响范围?
- 如何梳理服务依赖以及依赖的合理性?
- 如何分析链路性能问题以及实施容量规划?
分布式链路追踪,就是将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式 请求的调用情况几种展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等。
第一节 常见的链路跟踪技术
-
Cat
由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控、业务监控。集成方案是通过代码埋点,比如拦截器、过滤器等。对代码的侵入性很大,集成成本高,风险大。 -
zipkin
由twitter开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微服务架构中的延迟问题,包括:数据的收集、存储、查找和展现。该产品结合spring-cloud-sleuth使用较为简单,集成方便,但是功能比较简单。 -
skywalking
Skywalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种此插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。 -
Sleuth
SpringCloud提供的分布式系统中链路追踪解决方案。
注: SpringCloud Alibaba技术栈中没有自己提供的网关,我们可以采用 Sleuth来做链路追踪解决方案。
第二节 Sleuth介绍
SpringCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案。它大量借用了Google Dapper的设计,我们需要先了解Sleuth中的术语和相关概念。
+Trace
由一组Trace Id相同的Span串联形成一个树状结构。为了实现请求跟踪,当请求到达分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的标识(TraceId),同时在分布式系统内部流转的时候,框架始终保持传递该唯一值,直到整个请求的返回。那么我们可以使用该唯一标识将所有的请求串联起来,形成一条完整的请求链路。
- Span
代表一组基本的工作单元。为了统计各处理单元的延迟,当请求到达各个服务组件的时候,也通过一个唯一标识(SpanId)来标识它的开始、具体过程和结束。通过SpanId的开始和结束时间戳,就能统计出该Span的调用时间,除此之外,我们还可以获取如事件的名称,请求信息等元数据。 - Annotation
用它记录一段时间内的事件,内部使用的重要注释
cs(Client Send): 客户端发出的请求,开始一个请求的生命
sr(Server Received): 服务端接收到请求开始进行处理,sr-cs=网络延迟
ss(Server Send): 服务端处理完毕准备发送到客户端,ss-sr=服务器上的请求处理时间
cr(Client Received): 客户端接收到服务端的响应,请求结束。cr-cs=请求的总时间。
第三节 Sleuth入门
1. 如何使用Sleuth
- 由于我们的链路追踪是面向所有微服务的,所以只需要在父工程导入sleuth依赖
<!--链路追踪技术Sleuth-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
-
重新启动所有的模块,并清空控制台日志
-
发起下单请求,http://127.0.0.1:7000/server-order/order/prod/3,请求成功,查看控制台日志。(服务模块之间的调用关系见下图)
控制台日志
将三个服务的日志整合到一起查看。
2022-08-11 17:14:32.518 INFO [api-gateway,aa4a9e598e544259,aa4a9e598e544259,true] 96396 --- [ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty : Flipping property: server-order.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2022-08-11 17:14:32.586 INFO [api-gateway,aa4a9e598e544259,aa4a9e598e544259,true] 96396 --- [ctor-http-nio-2] c.netflix.loadbalancer.BaseLoadBalancer : Client: server-order instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=server-order,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2022-08-11 17:14:32.602 INFO [api-gateway,aa4a9e598e544259,aa4a9e598e544259,true] 96396 --- [ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater
2022-08-11 17:14:32.653 INFO [api-gateway,aa4a9e598e544259,aa4a9e598e544259,true] 96396 --- [ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty : Flipping property: server-order.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2022-08-11 17:14:32.656 INFO [api-gateway,aa4a9e598e544259,aa4a9e598e544259,true] 96396 --- [ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client server-order initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=server-order,current list of Servers=[192.168.199.1:8091],Load balancer stats=Zone stats: {unknown=[Zone:unknown; Instance count:1; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},Server stats: [[Server:192.168.199.1:8091; Zone:UNKNOWN; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@38eb896a
2022-08-11 17:14:32.884 INFO [server-order,aa4a9e598e544259,fd980b8a9889ddb4,true] 160040 --- [nio-8091-exec-8] com.lcz.controller.OrderController : 调用商品服务,调用商品微服务查询此商品
2022-08-11 17:14:32.901 INFO [server-order,aa4a9e598e544259,fd980b8a9889ddb4,true] 160040 --- [nio-8091-exec-8] com.lcz.controller.OrderController : 查询到的商品内容:{"pid":3,"pname":"鼠标","price":30.0,"stock":500}
2022-08-11 17:14:32.915 INFO [server-order,aa4a9e598e544259,fd980b8a9889ddb4,true] 160040 --- [nio-8091-exec-8] com.lcz.controller.OrderController : 用户下单成功,订单信息为:{"number":1,"uid":1,"pname":"鼠标","price":30.0,"pid":3,"oid":29,"username":"测试"}
2022-08-11 17:14:32.890 INFO [server-product,aa4a9e598e544259,d6b62e50e69ea14e,true] 166144 --- [nio-8081-exec-5] com.lcz.controller.ProductController : 查询商品信息pid:3
2022-08-11 17:14:32.898 INFO [server-product,aa4a9e598e544259,d6b62e50e69ea14e,true] 166144 --- [nio-8081-exec-5] com.lcz.controller.ProductController : 获取到商品信息:{"pid":3,"pname":"鼠标","price":30.0,"stock":500}
2. 日志格式解释
从前面我们抽取一行日志,解释一下各参数的意思。
INFO [api-gateway(服务名),aa4a9e598e544259(TraceId),aa4a9e598e544259(SpanId),true(是否将数据输出到第三方平台)]
第三节 Zipkin的介绍
前面我们使用Sleuth进行链路追踪,但是Sleuth并没有提供UI用于展示,直接通过日志去分析很不方便。
本节通过集成Zipkin进行日志聚合,并且通过zipkin的可视化展示和全文检索,方便我们进行查看和分析。
Zipkin是twitter的一个开源项目,它基于Google Dapper实现,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。
我们可以使用它来收集各个服务器上请求链路的跟踪数,并通过它提供的REST API接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。
除了面向开发的API接口之外,它也提供了方便的UI组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。
Zipkin提供了可插拔的数据存储方式,包括In-Memory、Mysql、Cassandra以及Elasticsearch。
图中是Zipkin的基础架构。
- Collector: 收集器组件。主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为zipkin内部处理的 span格式,以支持后续的存储、分析、展示等。
- Storage : 存储组件。主要对处理器接收到的跟踪信息,默认会将这些信息存储到内存中,我们可以修改此存储策略,通过使用其它存储组件将跟踪信息存储到数据库。
- RESTfule API: API组件。主要用来对外提供访问接口,比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。
- Web UI : UI组件。基于API组件实现的上层应用。通过UI组件,用户可以方便而直观的查询和分析跟踪信息。
Zipkin分为两段,一个Zipkin服务端,一个是 Zipkin客户端,客户端就是微服务的应用。
客户端会配置服务端的URL地址,一旦发生服务间的调用的时候,会被配置到微服务里面的Sleuth的监听器监听,并生成响应的Trace和Span信息发送到服务端。
zipkin官网https://zipkin.io/pages/quickstart.html
zip的Github开源代码地址:https://github.com/openzipkin/zipkin/
第四节 Zipkin安装
1. Zipkin服务端
- 下载Zipkin的jar包
https://search.maven.org/remote_content?g=io.zipkin&a=zipkin-server&v=LATEST&c=exec
- 通过命运行,输入命令运行Zipkin Server
java -jar zipkin-server-2.23.18-exec.jar
- 访问 http://localhost:9411/,刷新查看什么也没有,我们只有在微服务里集成了Zipkin客户端,Zipkin服务端才会显示信息。
2. Zipkin客户端集成
- 由于我们的链路追踪是面向所有微服务的,所以只需要在父工程导入sleuth依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
- 配置zipkin和sleuth,所有的微服务模块都需要配置(包含api-gateway)
spring:
zipkin:
base-url: http://localhost:9411/ #zipkin server的请求地址
discovery-client-enabled: false #让nacos把它当成一个URL,而不是当做服务名
sleuth:
sampler:
probability: 1.0 #日志采样的百分比
- 重启所有的微服务和网关,执行下单请求 http://127.0.0.1:7000/server-order/order/prod/3, 刷新查看zipkin, http://localhost:9411/
可以查看到这个请求链路的调用细节和耗时情况。
通过查看依赖,我们查看到微服务直接的依赖关系。