一、链路追踪简介
微服务架构的使用,从而使系统变得越来越复杂,原本单体的系统被拆成很多个服务,每个服务之间通过轻量级的 HTTP 协议进行交互。
单体架构时,一个请求的调用链路非常清晰,一般由负载均衡器,比如 Nginx。将调用方的请求转发到后端服务,后端服务进行业务处理后返回给调用方。而当架构变成微服务架构时,可能带来一系列的问题,比如下面三个问题:
- 接口响应慢,怎么排查?
- 服务间的依赖关系如何查看?
- 请求贯穿多个微服务,如何将每个请求的日志串起来?
引入分布式链路跟踪即可解决。
分布式链路跟踪原理在于如何能将请求经过的服务节点都关联起来。当一个请求从客户端到达网关后,相当于是第一个入口,这时就需要生成一个唯一的请求 ID,作为这次请求的标识。从网关到达服务 A 后,肯定是需要将请求 ID 传递到服务 A 中的,这样才能将网关到服务 A 的请求关联起来,依次类推,后面会经过多层服务,都需要将信息一层层传递。当然在每一层都需要将数据进行上报、统一存储、展示等操作。
从我们对这个需求的理解来看,链路跟踪并不是很复杂,而复杂的点在于如何实现这一套跟踪框架,就拿请求信息传递这件事来说,服务之间交互,有的用的是 Feign 调用接口,有的用的是 RestTemplate 调用接口,要想将信息传递到下游服务,那么必须得扩展这些调用的框架才可以。
核心概念
- Span :基本工作单元,例如,发送 RPC 请求是一个新的 Span,发送 HTTP 请求是一个新的 Span,内部方法调用也是一个新的 Span。
- Trace:一次分布式调用的链路信息,每次调用链路信息都会在请求入口处生成一个 TraceId。
- Annotation:用于记录事件的信息。在 Annotation 中会有 CS、SR、SS、CR 这些信息,前面的C表示客户端,S表示服务器端; 后面的S表示sent,也就是发起请求时的动作,R表示Received,也就是接受到请求时的动作;下面分别介绍下这些信息的作用。
- CS 也就是 Client Sent,客户端发起一个请求,这个 Annotation 表示 Span 的开始。
- CR 也就是 Client Received,表示 Span 的结束,客户端已成功从服务器端收到响应,用 CR 的时间戳减去 CS
的时间戳就可以知道客户端从服务器接收响应所需的全部时间。 - SS 也就是 Server Sent,在请求处理完成时将响应发送回客户端,用 SS 的间戳减去 SR
的时间戳会显示服务器端处理请求所需的时间。 - SR 也就是 Server Received,服务器端获得请求并开始处理它,用 SR 的时间戳减去 CS 的时间戳会显示网络延迟时间。
Spring Cloud Sleuth组件的主要功能是在分布式系统中提供服务追踪的解决方案。
为什么需要链路追踪??
微服务架构是通过业务来划分服务的,,使用 REST 调用。对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。
在微服务框架中,一个由客户端发起的请求在后端系统中经过多个不同的服务节点调用来协同生产最后的请求结果,每一个前段请求会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败
那该如何解决呢?
- sleuth : 链路追踪器
- zipkin:链路分析器(可视化)
1、Sleuth组件简介
Sleuth是SpringCloud微服务系统中的一个组件,实现了链路追踪解决方案。可以定位一个请求到底请求了哪些具体的服务。在复杂的微服务系统中,如果请求发生了异常,可以快速捕获问题所在的服务。
工作流程:
sleuth 记录的是一次请求链路(请求经过哪些服务,哪些类)
一条链路有个唯一标识(Trace ID), 每个经过一个链路(服务)使用Span来标识(记录请求相关信息), 各个span间使用parent ID 关联
2、项目结构
- 启动顺序如下
* 注册中心
node07-eureka-7001
* 链路数据收集服务
node07-zipkin-7003
* 服务提供
node07-provider-6001
node07-provider-6002
* 网关路由
node07-zuul-7002
二、搭建链路服务
1、核心依赖
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
- 启动类注解:@EnableZipkinServer
2、配置文件
server:
port: 7003
spring:
application:
name: node07-zipkin-7003
eureka:
instance:
hostname: zipkin-7003
prefer-ip-address: true
client:
service-url:
defaultZone: http://registry01.com:7001/eureka/
三、微服务配置
这里网关,zuul-7002,服务提供,provider-6001,provider-6002的配置相同。
1、核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
2、配置文件
spring:
zipkin:
base-url: http://localhost:7003
sleuth:
sampler:
# 数据 100% 上传
percentage: 1.0
四、测试流程
1、注册中心
一次启动上述服务之后,查看注册中心:
2、请求流程
访问接口
http://localhost:7002/v1/api-6001/get6001Info
这个请求从网关服务进入,到达6001端口服务之后,请求6002端,最终返回结果。
- 6001接口
@Autowired
private RestTemplate restTemplate ;
@RequestMapping("/get6001Info")
public String get6001Info (){
String server_name = "http://node07-provider-6002" ;
return restTemplate.getForObject(server_name+"/get6002Info",String.class) ;
}
- 6002接口
@RequestMapping(value = "/get6002Info",method = RequestMethod.GET)
public String get6002Info () {
LOG.info("provider-6002");
return "6002Info" ;
}
3、链路管理界面
Zipkin:
zipkin是Twitter基于google的分布式监控系统Dapper(论文)的开发源实现,
zipkin用于跟踪分布式服务之间的应用数据链路,分析处理延时,帮助我们改进系统的性能和定位故障。
官网:https://zipkin.io/
1)、UI界面
访问接口
http://localhost:7003/zipkin/
2)、依赖分析
如图点击,【依赖分析】,和上面描述的请求过程完全一致。