源码:https://github.com/GiraffePeng/spring-cloud-scaffolding
服务调用全链路跟踪
针对调用链路跟踪,Spring Cloud的组件Sleuth通过集成zipkin提供了一种解决方案,本文主要讲述Sleuth+ZipKin的集成。Spring Cloud Sleuth 的主要功能就是为 分布式系统提供追踪解决方案,并且兼容支持了Zipkin,只需要在pom.xml文件中引入相应的依赖即可。它主要用于聚集来自各个异构系统的实时监控数据,用来追踪微服务架构下的系统延时问题。
1、基本术语
1.1、Span
Span 是一个基本的 工作单元,用于描述一次 RPC 调用,Span 通过一个 64 位的 spanId 作为 唯一标识。Zipkin 中的 Span 还有其他数据信息,比如 摘要、时间戳事件、关键值注释 (tags) 以及 进度 ID (通常是 IP 地址)。Span 在不断的启动和停止,同时记录了 时间信息,一个 Span 创建后,必须在未来的某个时刻停止它。
1.2、Trace
Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式大数据工程,你可能需要创建一个trace。
1.3、Annotation
表示基本标注列表,一个Annotation可以理解成Span生命周期中重要时刻的数据快照,比如一个Annotation中一般包含发生时刻(timestamp)、事件类型(value)、端点(endpoint)等信息。其中 Annotation 的 事件类型 包含以下四类:
- cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始
- sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟
- ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间
- cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间
2、Spring Cloud Sleuth
实际项目中若已引入Spring Could Sleuth包,通过上述的术语,则默认会在打印日志时输出traceId、spanId等内容,若它调用一个也是用Spring Could Sleuth的服务,则会自动传递traceId
类似这种traceId的传递操作,在服务内多采用ThreadLocal或MDC的方式,在分布式微服务时一般在request header或url参数中传递。
3、Zipkin
Zipkin是一个开放源代码分布式的跟踪系统,每个服务向zipkin报告计时数据,zipkin会根据调用关系通过Zipkin UI生成依赖关系图。
Zipkin提供了可插拔数据存储方式:In-Memory、MySql、Cassandra以及Elasticsearch。为了方便在开发环境我直接采用了In-Memory方式进行存储,生产数据量大的情况则推荐使用Elasticsearch。
如果一个服务的调用关系如下:
那么此时将Span和Trace在一个系统中使用Zipkin注解的过程图形化:
4、Sleuth + Zipkin 工程搭建
4.1、版本选择:
Spring Cloud - Finchley.RELEASE
Spring Boot - 2.0.3.RELEASE
Zipkin - 2.11.6
4.2、项目准备:
- spring-cloud-eureka-server注册中心,端口8865
- spring-cloud-zuul-server服务网关,端口8866
- spring-cloud-auth-server授权服务,端口8599
- spring-cloud-userservice-server用户业务服务,端口8761
上述4个项目都在github的源码中能够找到,本次链路跟踪主要模拟的场景是通过网关访问user用户服务,然后进行调用auth服务授权并且登陆与注册的场景。
因为使用的Spring Boot的版本为2.0版本以上,zipkin官方建议不进行自己集成,而是通过使用官方提供的zipkin的jar包进行部署zipkin项目。
- 搭建方式详见官网 :Github:zipkin
- jar包下载地址:zipkin的jar包下载
此处使用2.11.6版本。
4.3、项目的改造
我们需要在被Zipkin监控的服务上进行改造,达到能够通过Sleuth将各种上述术语提到的节点主动上报Zipkin的功能。
这里需要被监控的是spring-cloud-zuul-server、spring-cloud-auth-server、spring-cloud-userservice-server
4.3.1 引入依赖
在上述的三个需要被监控的项目pom.xml中加入zipkin的引入。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
4.3.2 配置属性
同样,在上述三个项目的application.yml或者applicaiton.properties中加入对zipkin的支持,以userservice为例(只展示部分的配置属性,全部的可查询源码)。
server:
port: 8761
spring:
application:
name: userservice
client:
service-url:
defaultZone: http://localhost:8865/eureka/
sleuth:
sampler:
percentage: 1.0
zipkin:
# zipkin的连接地址
base-url: http://localhost:9411/
# 若在同一个注册中心的话可以启用自动发现,省略base-url
# locator:
# discovery:
# enabled: true #自动发现
这里说明下配置的关键属性
- spring.sleuth.sampler.percentage: 链路调用的收集率,全链路监控抽样概率100%,也就是1.0(默认10%,丢数据太多不方便观察结果)
- spring.zipkin.base-url:需要连接的zipkin服务的地址,默认端口9411
- spring.zipkin.locator.discovery.enabled: 若在同一个注册中心可以启动自动发现,省略base-url,这里因为使用的官方提供的jar包,默认不会注册到自己搭建的注册中心,所以不使用该方式。
到这里可以发现,引入ZipKin服务只需要导依赖、配置属性,两步即可。
4.4 启动验证
ok,基本上的改造大功告成,接下来进行测试。
4.4.1 启动zipkin的jar包
windows的话打开cmd,转移到jar包相应的目录下,录入命令:
java -jar zipkin-server-2.11.6-exec.jar
启动后命令窗口展示如下:
4.4.2 启动本身服务
依次启动准备的4个项目,eureka、zuul、auth、user,启动后为了形成链路,需要调用接口。
这里调用用户的登录接口。
这里调用用户的注册接口。
4.4.3 验证
在浏览器上输入zipkin的访问地址:http://localhost:9411/zipkin/ ,打开的界面如下:
先通过默认的点击Find Traces按钮,可以看到如下信息:
点击其中一个链路,会展示该链路的详细信息,包括请求的达到服务的顺序,每个服务的耗时,每个服务上调用的内容等:
点击其中的一个服务,还可以看到更详细的信息
还有一种场景,就比如我们通过日志查看该条日志的链路地址怎么办?
本场景下的入口服务为zuul,打开zuul的日志,因为使用了Sleuth,它会格式化我们服务的日志
红圈中的为 注册接口的日志, 通过服务名称、traceId、spanId、是否发送至zipkin为格式打印日志,只需要找到你想要查看的traceId在zipkin上根据traceId搜索即可。
同时zipkin还提供了服务之间的调用链路的展示。
可以看到zuul通过路由分发至user,然后user通过feign调用了auth。