随着业务的不断发展和系统壮大,一般系统都会经过由早期的业务集中性,逐渐发展到中期的业务分离与模块化的扩展性、健壮性,再到后期的高稳定性、高可维护性,这一路上的演进、系统拆分等将会导致系统调用链路越来越复杂。
比如一个前端请求到达后台后,可能最终需要涉及多个模块或者调用很多次后台服务才能完成业务处理,而当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些后台服务引起的(这个时候往往会让人很头疼,如果有服务调用关系图就有如神助),这时就需要解决如何快速定位服务故障点,以对症下药;又或者一系列接口调用过程中查找并定位慢接口等等,于是,我们需要分布式服务调用跟踪链。
现阶段,分布式服务跟踪方案使用最为广泛的开源实现是 Twitter 的 Zipkin。为了实现平台无关、厂商无关的分布式服务跟踪,云原生计算基金会CNCF发布了布式服务跟踪标准 Open Tracing。国内,淘宝的 “鹰眼”、京东的 “Hydra”、大众点评的 “CAT”、新浪的 “Watchman”、唯品会的 “Microscope” 等等,都是这样的系统。所以,链路监控作为监控平台一部分,尤为重要。
Spring Cloud Sleuth 我们提供了一套完整的解决方案。Spring Cloud Sleuth 可以结合 Zipkin,将信息发送到 Zipkin,利用 Zipkin 的存储来存储信息,利用 Zipkin UI 来展示数据。在本章中,我们将详细介绍如何使用 Spring Cloud Sleuth + Zipkin 来为我们的微服务架构增加分布式服务调用链路跟踪的能力。
服务链路跟踪功能具体化的话,就是服务与服务之间调用关系的监控,这么理解的话,想一想,是不是有想起来之前在做 Spring Cloud Ribbon + REST 服务消费的时候,有具体化到调用服务提供者?
嗯,没错,这里我们继续使用之前已经做好的微服务模块来进行改造,快进到此的朋友则可能需要先看看 第一节的Eureka服务注册与发现 和 第二节的服务消费者。
进入 Zipkin 官网:https://zipkin.io/pages/quickstart.html
官方提供了一键脚本,分别执行以下两个命令对 Zipkin 进行下载安装和运行。
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar
当启动 Zipkin 后,浏览器访问:http://localhost:9411/zipkin/ 就能看到如下界面:
UI界面的TOP功能菜单依次为:
到此,Zipkin 服务端就 OK 了。
改造服务提供者(wei-service-provider),源码参见 第一节。
pom.xml 添加以下服务链路跟踪实现的核心依赖:
org.springframework.cloud
spring-cloud-starter-sleuth
org.springframework.cloud
spring-cloud-starter-zipkin
如此,pom.xml 文件的完整依赖如下:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-sleuth
org.springframework.cloud
spring-cloud-starter-zipkin
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
application.yml 添加以下配置项:
spring.sleuth.web.client.enabled=true
spring.sleuth.sampler.probability=1.0
spring.zipkin.base-url=http://localhost:9411/
如此,application.yml 文件的完整配置如下:
server:
port: 8010
spring:
application:
name: wei-service-provider # 指定进行服务注册时该服务的名称,服务与服务之间相互调用一般都是根据这个name
sleuth:
web:
client:
enabled: true
sampler:
probability: 1.0 # 将采样比例设置为1.0,也就是全部都需要。默认是0.1
zipkin:
base-url: http://localhost:9411/ # 指定了 Zipkin 服务器的地址
eureka:
client:
service-url:
defaultZone: http://localhost:8090/eureka/ # 指定进行服务注册地址
Spring Cloud Sleuth 有一个 Sampler 策略,可以通过这个实现类来控制采样算法。采样器不会阻碍 span 相关 id 的产生,但是会对导出以及附加事件标签的相关操作造成影响。Sleuth 默认采样算法的实现是 Reservoir sampling,具体的实现类是 PercentageBasedSampler,默认的采样比例为: 0.1(即10%)。不过我们可以通过 spring.sleuth.sampler.probability 来设置,所设置的值介于 0.0 到 1.0 之间,1.0 则表示全部采集。
端口9411为Zipkin默认端口号。
如此,服务提供者(wei-service-provider)就改造完成了。
改造服务消费者(wei-consumer-ribbon),源码参见第二节。
pom.xml 添加以下服务链路跟踪实现的核心依赖:
org.springframework.cloud
spring-cloud-starter-sleuth
org.springframework.cloud
spring-cloud-starter-zipkin
如此,pom.xml 文件的完整依赖如下:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.cloud
spring-cloud-starter-sleuth
org.springframework.cloud
spring-cloud-starter-zipkin
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
application.yml 添加以下配置项:
spring.sleuth.web.client.enabled=true
spring.sleuth.sampler.probability=1.0
spring.zipkin.base-url=http://localhost:9411/
如此,application.yml 文件的完整配置如下:
server:
port: 8024
spring:
application:
name: wei-consumer-ribbon # 指定进行服务注册时该服务的名称,服务与服务之间相互调用一般都是根据这个name
sleuth:
web:
client:
enabled: true
sampler:
probability: 1.0 # 将采样比例设置为1.0,也就是全部都需要。默认是0.1
zipkin:
base-url: http://localhost:9411/ # 指定了 Zipkin 服务器的地址
eureka:
client:
service-url:
defaultZone: http://localhost:8090/eureka/ # 指定进行服务注册的地址
好了,服务消费者/调用者(wei-consumer-ribbon)也改造完成了。
至此,代码改造完成。
确认已经依次正常启动以下应用模块:
Spring 应用在监测到 classpath 中有 Sleuth 和 Zipkin 后,会自动在 WebClient 或者 RestTemplate 的调用过程中向 HTTP 请求注入追踪信息,并向 Zipkin Server 发送这些信息。
到此,测试准备就绪。
我们先看看 Zipkin UI:http://localhost:9411/zipkin/,此时如果点击【Find Traces】没有任务调用信息的。
那,我们让他们产生调用关系,浏览器访问:http://localhost:8024/demo/info?name=tester,返回:
Hi,tester,我是服务,我被调用了,服务名为:wei-service-provider,端口为:8010[Ribbon + REST]
我们再去看看 Zipkin UI:http://localhost:9411/zipkin/,点击【Find Traces】看看有没有发生什么变化:
搜索结果列表出现了一条记录,这就是我们想要看到的。点进去看看:
我们可以看到每一个服务的调用顺序和所耗时间。可以清楚的看到每一个接口的深度。
而当我们把访问一个错误的请求时,比如,去掉参数的URL访问:http://localhost:8024/demo/info,将会返回错误页面。此时,刷新 Zipkin 会发现列表中出现了朱红色的请求失败的记录。这无疑是一个很好的快速定位问题和服务预警的利器。
点它查看详细错误信息,可以快速定位到接口和方法,是不是一目了然。
点击依赖分析,可以看到应该之间的调用关系。如果调用关系过于复杂,通过 Zipkin 也将会一览无余。
然而
Zipkin 服务端,在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,而是直接提供了编译好的 jar 包来给我们使用(就是前面我们通过一键脚本下载安装的Zipkin),详情请看 https://github.com/openzipkin/zipkin/issues/1962 : upgrade to Spring Boot 2.0 NoClassDefFoundError UndertowEmbeddedServletContainerFactory #1962
并且
并且以前的 @EnableZipkinServer 也已经被打上了 @Deprecated
If you decide to make a custom server, you accept responsibility for troubleshooting your build or configuration problems, even if such problems are a reaction to a change made by the OpenZipkin maintainers. In other words, custom servers are possible, but not supported.
EnableZipkinServer.java:https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/java/zipkin/server/EnableZipkinServer.java
所以
简而言之就是:私自改包,后果自负。
消息总线 RabbitMQ:
说了这么些,情况这么复杂,所以,我们需要整合 Spring Cloud Sleuth+Zipkin+RabbitMQ。
Zipkin 概念图:
经过上面的实践,回过头来再看看这张 Zipkin 流程图,定睛一看,有没有觉得原来好简单~
Spring Cloud Sleuth
一般的,一个分布式服务跟踪系统主要由三部分构成:
根据系统大小不同,每一部分的结构又有一定变化。譬如,对于大规模分布式系统,数据存储可分为实时数据和全量数据两部分,实时数据用于故障排查(Trouble Shooting),全量数据用于系统优化;数据收集除了支持平台无关和开发语言无关系统的数据收集,还包括异步数据收集(需要跟踪队列中的消息,保证调用的连贯性),以及确保更小的侵入性;数据展示又涉及到数据挖掘和分析。虽然每一部分都可能变得很复杂,但基本原理都类似。
https://windmt.com/2018/04/24/spring-cloud-12-sleuth-zipkin/
http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#_spring_cloud_sleuth
SpringCloud进击 | 一浅出:服务注册与发现(Eureka)【Finchley版本】
SpringCloud进击 | 二浅出:服务消费者(Ribbon+REST)【Finchley版本】
SpringCloud进击 | 三浅出:服务消费者(Feign)【Finchley版本】
SpringCloud进击 | 四浅出:断路器与容错(Hystrix)【Finchley版本】
SpringCloud进击 | 五浅出:服务网关 - 路由(Zuul Router)【Finchley版本】
SpringCloud进击 | 六浅出:服务网关 - 过滤器(Zuul Filter)【Finchley版本】
SpringCloud进击 | 七浅出:配置中心(Git配置与更新)【Finchley版本】
SpringCloud进击 | 一深入:配置中心(服务化与高可用)【Finchley版本】
SpringCloud进击 | 二深入:配置中心(消息总线)【Finchley版本】
SpringCloud进击 | 三深入:服务链路跟踪(Spring Cloud Sleuth)【Finchley版本】
SpringCloud进击 | 四深入:服务链路跟踪(Sleuth+Zipkin+RabbitMQ整合)【Finchley版本】
SpringCloud进击 | 五深入:断路器监控(Hystrix Dashboard)【Finchley版本】
SpringCloud进击 | 六深入:断路器聚合监控(Hystrix Turbine)【Finchley版本】
SpringCloud进击 | 七深入:高可用的服务注册中心【Finchley版本】
下一节,请继续关注:SpringCloud进击 | 四深入:服务链路跟踪(Sleuth+Zipkin+RabbitMQ整合)【Finchley版本】