分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】
Spring Cloud Sleuth
Span
是基本的工作单位。 例如,发送 RPC
是一个新的跨度,就像向RPC发送响应一样。 跨度由跨度唯一的64位ID和跨度所包含的另一个64位ID标识。 Spans还有其他数据,例如描述,键值注释,导致它们的跨度的ID以及进程ID(通常为IP地址)。 跨度启动和停止,并且他们跟踪他们的时间信息。 一旦你创建了一个跨度,你必须在将来某个时候停止它。 一组Spans形成一个叫做Trace的树状结构。 例如,如果您正在运行分布式大数据存储,则跟踪可能由放入请求组成。
一般的,一个分布式服务跟踪系统主要由三部分构成:
根据系统大小不同,每一部分的结构又有一定变化。譬如,对于大规模分布式系统,数据存储可分为实时数据和全量数据两部分,实时数据用于故障排查(Trouble Shooting),全量数据用于系统优化;数据收集除了支持平台无关和开发语言无关系统的数据收集,还包括异步数据收集(需要跟踪队列中的消息,保证调用的连贯性),以及确保更小的侵入性;数据展示又涉及到数据挖掘和分析。虽然每一部分都可能变得很复杂,但基本原理都类似。
服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为止的过程,称为一个 trace。每个 trace 中会调用若干个服务,为了记录调用了哪些服务,以及每次调用的消耗时间等信息,在每次调用服务时,埋入一个调用记录,称为一个 span。这样,若干个有序的 span 就组成了一个 trace。在系统向外界提供服务的过程中,会不断地有请求和响应发生,也就会不断生成 trace,把这些带有 span 的 trace 记录下来,就可以描绘出一幅系统的服务拓扑图。附带上 span 中的响应时间,以及请求成功与否等信息,就可以在发生问题的时候,找到异常的服务;根据历史数据,还可以从系统整体层面分析出哪里性能差,定位性能优化的目标。
Spring Cloud Sleuth 为服务之间调用提供链路追踪。通过 Sleuth 可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。从而让我们可以很方便的理清各微服务间的调用关系。此外 Sleuth 可以帮助我们:
耗时分析: 通过 Sleuth 可以很方便的了解到每个采样请求的耗时,从而分析出哪些服务调用比较耗时; 可视化错误: 对于程序未捕捉的异常,可以通过集成 Zipkin 服务界面上看到; 链路优化: 对于调用比较频繁的服务,可以针对这些服务实施一些优化措施。 Spring Cloud Sleuth 可以结合 Zipkin,将信息发送到 Zipkin,利用 Zipkin 的存储来存储信息,利用 Zipkin UI 来展示数据。
这是 Spring Cloud Sleuth 的概念图:color
的颜色表示一个 span
(有七个 spans
- 从A到G)。 考虑以下说明:
Trace Id = X
Span Id = D
Client Sent
本说明指出当前的跨度(span)将跟踪标识设置为X,跨度标识设置为D.此外还发生了客户端已发送事件。
下图显示了跨度(span)的父子关系:
Zipkin
Zipkin 是 Twitter 的一个开源项目,它基于 Google Dapper 实现,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。 我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。除了面向开发的 API 接口之外,它也提供了方便的 UI 组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。 Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。接下来的测试为方便直接采用 In-Memory 方式进行存储,生产推荐 Elasticsearch。
上图展示了 Zipkin 的基础架构,它主要由 4 个核心组件构成:
快速上手
Zipkin 分为两端,一个是 Zipkin 服务端,一个是 Zipkin 客户端,客户端也就是微服务的应用。 客户端会配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端。 发送的方式主要有两种,一种是 HTTP 报文的方式,还有一种是消息总线的方式如 RabbitMQ。
不论哪种方式,我们都需要:
Zipkin服务端
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
application.yml
spring:
application:
name: zipkin-server
server:
port: 9411
看起来似乎很简单,不过springboot2.x过后更简单!关于 Zipkin 的服务端,在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,反而是直接提供了编译好的 jar 包来给我们使用,详情参考连接如果你的jdk是1.8+可以使用如下方式:
$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
$ java -jar zipkin.jar
如果你的是docker部署请:
docker run -d -p 9411:9411 openzipkin/zipkin
Zipkin客户端
导入核心依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
spring-cloud-starter-zipkin
依赖内部包含了两个依赖,等于同时引入了 spring-cloud-starter-sleuth
, spring-cloud-sleuth-zipkin
两个依赖。名字特别像,注意区分。
我的springgateway的配置文件 application.yml
## SERVER
server:
port: 8764
management:
server:
port: 9275
endpoints:
web:
exposure:
include: "*"
base-path: /actuator
path-mapping:
health: /healthcheck
info: /infocheck
eureka:
instance:
hostname: localhost
health-check-url-path: ${management.endpoints.web.base-path}${management.endpoints.web.path-mapping.health}
status-page-url-path: ${management.endpoints.web.base-path}${management.endpoints.web.path-mapping.info}
client:
service-url:
defaultZone: http://localhost:8763/eureka/
server:
renewal-percent-threshold: 0.8
spring:
application:
name: gateway #1
zipkin:
base-url: http://localhost:9411 #2
sleuth:
sampler:
probability: 1.0 #3
总结:
本篇文章参考官网讲解了一下 SpringCloudSleuth
实现链路监控的一些知识点,以及一些简单的入门使用,最重要的是注意版本是 Springboot2.x
,官方已经推荐使用它自己的 zipkin
服务端的jar包了,尽量别自行修改代码,否则出现问题不好解决!
参考资料
Spring Cloud Sleuth官方资料
http://cloud.spring.io/spring-cloud-sleuth/single/spring-cloud-sleuth.html#_distributed_tracing_with_zipkin
openzipkin/zipkin
https://github.com/openzipkin/zipkin
spring4all社区资料【使用Spring Cloud Sleuth实现链路监控】
http://www.spring4all.com/article/156