原文请参考Spring Cloud构建微服务架构:分布式服务跟踪(入门)【Dalston版】和 Spring Cloud构建微服务架构:分布式服务跟踪(跟踪原理)【Dalston版】我只是在学习过程中,记录一下,加深记忆和理解。
使用Spring Cloud Sleuth来为我们的微服务架构增加分布式服务跟踪的能力。
准备工作
1.服务注册中心eureka-server
2.创建微服务trace-1:实现一个REST接口/trace-1
,调用该接口后将通过Ribbon触发对trace-2
应用的调用。
#指定微服务名称 使用微服务名称就可以访问微服务
spring.application.name=trace-1
#指定微服务端口
server.port=9101
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
/trace-1
,调用该接口后将通过Ribbon触发对trace-2
应用的调用package com.example.trace1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class Trace1Controller {
@Autowired
private RestTemplate restTemplate;
Logger logger = LoggerFactory.getLogger(Trace1Controller.class);
@RequestMapping(value = "/trace-1", method = RequestMethod.GET)
public String trace() {
logger.info("===call trace-1===");
return restTemplate.getForEntity("http://trace-2/trace-2", String.class).getBody();
}
}
3.微服务trace-2 :实现一个REST接口/trace-2
,供trace-1
调用
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=trace-2
#微服务端口
server.port=9102
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
/trace-2 供trace-1微服务调用
package com.example.trace2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Trace2Controller {
Logger logger = LoggerFactory.getLogger(Trace2Controller.class);
@RequestMapping(value = "/trace-2", method = RequestMethod.GET)
public String trace() {
logger.info("======");
return "Trace";
}
}
4.将eureka-server
、trace-1
、trace-2
三个应用都启动起来,trace-1调用微服务trace-2,看log
通过postman或curl等工具来对trace-1
的接口发送请求http://localhost:9101/trace-1
,我们可以得到返回值Trace
在trace-1的控制台可以看到log如下
2020-08-05 10:59:14.715 INFO 13304 --- [nio-9101-exec-1] com.example.trace1.Trace1Controller : ===call trace-1===
在trace-2的控制台可以看到log如下
2020-08-05 10:59:14.992 INFO 20684 --- [nio-9102-exec-1] com.example.trace2.Trace2Controller : ======
到此都还没用到netflix sleuth的跟踪功能,只是看一下没有sleuth跟踪功能的微服务的日志是以上这样的。
5.为上面的trace-1
和trace-2
来添加服务跟踪功能
为应用添加服务跟踪能力, 只需要在pom.xml
依赖管理中增加spring-cloud-starter-sleuth
依赖即可
6.再次启动trace-1和trace2,然后发起请求qingqhttp://localhost:9101/trace-1
在trace-1的控制台可以看到log如下
2020-08-05 11:10:43.789 INFO [trace-1,cecade953d92daa9,cecade953d92daa9,true] 13452 --- [nio-9101-exec-1] com.example.trace1.Trace1Controller : ===call trace-1===
在trace-2的控制台可以看到log如下
2020-08-05 11:10:44.060 INFO [trace-2,cecade953d92daa9,e77155b746684779,true] 16956 --- [nio-9102-exec-1] com.example.trace2.Trace2Controller : ======
7.Spring Cloud Sleuth解释
从上面log中,我们可以看到多了一些形如[trace-1,cecade953d92daa9,cecade953d92daa9,true]
的日志信息,而这些元素正是实现分布式服务跟踪的重要组成部分,它们每个值的含义如下:
trace-1
,应用名称,也就是application.properties
中spring.application.name
参数配置的属性。f410ab57afd5c145
,Spring Cloud Sleuth生成的一个ID,称为Trace ID,它用来标识一条请求链路。一条请求链路中包含一个Trace ID,多个Span ID。a9f2118fa2019684
,Spring Cloud Sleuth生成的另外一个ID,称为Span ID,它表示一个基本的工作单元,比如:发送一个HTTP请求。true
,表示是否要将该信息输出到Zipkin等服务中来收集和展示。Spring Cloud Sleuth实现 分布式系统中的服务跟踪 有两个关键点 Trace ID
和Span ID
Trace ID
,从而将整个分布于不同微服务进程中的请求跟踪信息串联起来,以上面输出内容为例,trace-1
和trace-2
同属于一个前端服务请求来源,所以他们的Trace ID
是相同的,处于同一条请求链路中。8.spring-cloud-starter-sleuth依赖
在项目中引入spring-cloud-starter-sleuth
依赖之后, 它会自动的为当前应用构建起各通信通道的跟踪机制,比如:
RestTemplate
发起的请求trace-1
对trace-2
发起的请求是通过RestTemplate
实现的,所以spring-cloud-starter-sleuth
组件会对该请求进行处理,在发送到trace-2
之前sleuth会为在该请求的Header中增加实现跟踪需要的重要信息,主要有下面这几个:
9.自定义要输出的跟踪信息
修改Trace2Controller如下
package com.example.trace2;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Trace2Controller {
Logger logger = LoggerFactory.getLogger(Trace2Controller.class);
@RequestMapping(value = "/trace-2", method = RequestMethod.GET)
public String trace(HttpServletRequest request) {
// logger.info("======");
logger.info("======", request.getHeader("X-B3-TraceId"),
request.getHeader("X-B3-SpanId"));
return "Trace";
}
}
再次发送请求http://localhost:9101/trace-1
,在trace-2的控制台可以看到log如下,多了一些跟踪信息的内容
2020-08-07 16:36:04.617 INFO [trace-2,6cc6f23b1789ccc4,a1c6088c16dfac6f,true] 25712 --- [nio-9102-exec-1] com.example.trace2.Trace2Controller : ======
10.自定义要输出的跟踪信息 将Spring MVC的请求分发日志级别调整为DEBUG
级别
可以通过application.properties
中增加下面的配置,来将Spring MVC的请求分发日志级别调整为DEBUG
级别
logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG
再次发送请求http://localhost:9101/trace-1
,在trace-2的控制台可以看到log如下,多了一些跟踪信息的内容
2020-08-07 16:40:23.065 DEBUG [trace-2,c52101d193372b1d,d66e7ace3aaef4b9,true] 7796 --- [nio-9102-exec-1] o.s.web.servlet.DispatcherServlet : GET "/trace-2", parameters={}
2020-08-07 16:40:23.083 INFO [trace-2,c52101d193372b1d,d66e7ace3aaef4b9,true] 7796 --- [nio-9102-exec-1] com.example.trace2.Trace2Controller : ======
2020-08-07 16:40:23.098 DEBUG [trace-2,c52101d193372b1d,d66e7ace3aaef4b9,true] 7796 --- [nio-9102-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK