SPRING CLOUD微服务实战笔记--分布式服务跟踪:Spring Cloud Sleuth
Spring Cloud Sleuth
- 快速入门
- 准备工作
- 实现跟踪
- 跟踪原理
- 与Logstash整合
- 与ZipKin整合
- HTTP收集
- 消息中间件收集
- 数据存储
快速入门
准备工作
- 服务注册中心:eureka-server,可以直接使用之前的工程
微服务应用:trace-1,实现一个REST接口/trace-1,调用该接口后将触发对trace-2应用的调用
具体实现如下:
1)创建一个基础的Spring Boot应用,在pom.xml中增加依赖:
org.springframework.cloud
spring-cloud-starter-eureka
1.4.6.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-ribbon
1.4.6.RELEASE
org.springframework.boot
spring-boot-starter-test
test
2)创建主类,实现/trace-1接口,并使用RestTemplate调用trace-2应用的接口
@RestController
@EnableEurekaClient
@SpringBootApplication
public class HelloApplication {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
@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();
}
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
3)在application.properties
中,将eureka.client.serviceUrl.defaultZone
参数指向eureka-server
地址
spring.application.name=trace-1
server.port=9101
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
微服务应用:trace-2,实现一个REST接口/trace-2,供trace-1调用
1)创建一个基础的SpringBoot应用,pom.xml的依赖与trace-1相同
2)创建应用主类,并实现/trace-2接口,具体如下:@RestController
@EnableEurekaClient
@SpringBootApplication
public class HelloApplication {
private final Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping(value = “/trace-2”,method = RequestMethod.GET)
public String trace(){logger.info("===<call trace-2>====");
return "Trace";
}
public static void main(String[] args) {SpringApplication.run(HelloApplication.class, args);
}
}
3)在application.properties中,将eureka.client.serviceUrl.defaultZone参数指向eureka-server地址,并设置不同的应用名与端口
spring.application.name=trace-2
server.port=9102
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
- 启动eureka-server,trace-1,trace-2三个应用,发送请求
http://localhost:9101/trace-1
,可以看到返回值Trace,同时trace-1控制台打印===call trace-1====
,trace-2控制台打印===<call trace-2>====
实现跟踪
在trace-1和trace-2的pom.xml依赖管理中增加spring-cloud-starter-sleuth
依赖即可
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
重启trace-1和trace-2后,控制台打印发生变化,
INFO [trace-1,ddcf47da76da68c7,ddcf47da76da68c7,false] 70283 --- [nio-9101-exec-1] ication$$EnhancerBySpringCGLIB$$84347891 : ===call trace-1====
INFO [trace-2,ddcf47da76da68c7,248958640a14c496,false] 70280 --- [nio-9102-exec-1] ication$$EnhancerBySpringCGLIB$$84347891 : ===<call trace-2>====
可以看到增加了[trace-2,ddcf47da76da68c7,ddcf47da76da68c7,false]
类似的日志信息,含义如下:
- 第一个值:trace-1,记录应用的名称
- 第二个值:ddcf47da76da68c7,Spring Cloud Sleuth生成的一个ID,成为TraceID,用来标识一条请求链路。一条请求链路包含一个TraceId
- 第三个值:248958640a14c496,Spring Cloud Sleuth生成的另一个ID,成为Span ID,表示一个基本的工作单元,比如发送一个HTTP请求
- 第四个值:false,表示是否要将该信息输出到Zipkin等服务中来收集和展示
在一次服务请求链路的调用过程中,会保持并传递同一个Traceid,从而将整个分布于不同微服务进程中的请求跟踪信息串联起来。如上面例子,trace-1与trace-2同属于一个前端服务请求来源,所以它们的TraceID相同,处于同一条请求链路中。
跟踪原理
TraceID和SpanID是Spring Cloud Sleuth实现分布式服务跟踪的核心
- 通过唯一跟踪标识TraceID的记录,能将所有请求过程的日志关联起来
- SpanID可以统计各处理单元的时间延迟,还可以包含一些其他数据,比如事件名称,请求信息等
spring-cloud-starter-sleuth
组件在转发请求的Header中增加实现跟踪需要的重要信息,主要有下面几个: - X-B3-TraceId:一条请求链路(Trace)的唯一标识,必需的值
- X-B3-SpanId:一个工作单元(Span)的唯一标识,必需的值
- X-B3-ParentSpanId:标识当前工作单元所属的上一个工作单元,RootSpan(请求链路的第一个工作单元)的该值为空
X-Span-Name:工作单元的名称
1.对trace-1和trace-2的实现进行修改@RequestMapping(value = “/trace-1”,method = RequestMethod.GET)
public String trace(HttpServletRequest request){
logger.info("====<call trace-1>=====,TraceId={},SpanId={},ParentSpanId={},Sampled={},SpanName={}"
,request.getHeader("X-B3-TraceId"),request.getHeader("X-B3-SpanId")
,request.getHeader("X-B3-ParentSpanId"),request.getHeader("X-B3-Sampled"),request.getHeader("X-Span-Name"));
return restTemplate().getForEntity("http://trace-2/trace-2",String.class).getBody();
}
@RequestMapping(value = “/trace-2”,method = RequestMethod.GET)
public String trace(HttpServletRequest request){
logger.info("====<call trace-2>=====,TraceId={},SpanId={},ParentSpanId={},Sampled={},SpanName={}"
,request.getHeader("X-B3-TraceId"),request.getHeader("X-B3-SpanId")
,request.getHeader("X-B3-ParentSpanId"),request.getHeader("X-B3-Sampled"),request.getHeader("X-Span-Name"));
return "Trace";
}
2.在trace-1和trace-2的application.properties
中加入配置,可以更加直观的观察跟踪信息
logging.level.org.springframework.web.servlet.DispatcherServlet=debug
重启trace-1和trace-2的应用,可以看到
trace-1的控制台
trace-2的控制台
trace-2中的ParentSpanId
就是trace-1中的SpanId
,trace-2中的TraceId
与trace-1中的TraceId
相同
与Logstash整合
由于日志文件都离散地存储在各个服务实例的文件系统之上,引入基于日志的分析系统是一个不错的选择,比如ELK平台,它可以轻松地收集和存储跟踪日志,同时还可以根据TraceId搜索出对应请求链路相关的明细日志
ELK平台主要由ElasticSearch、Logstash和Kibana三个工具组成
- ElasticSearch是一个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,RESTful风格接口,多数据源,自动搜索负载等
- Logstash是一个完全开源的工具,它可以对日志进行收集、过滤,并将其存储供以后使用
- Kibana也是一个开源和免费的工具,可以为Logstash和ElasticSearch提供日志分析友好的Web界面,可以帮助汇总、分析和搜索重要数据日志
如何实现面向Logstash的日志输出配置 在pom.xml中新增依赖
net.logstash.logback
logstash-logback-encoder
4.6 在工程/resource目录下创建bootstrap.properties配置,并将
spring.application.name=trace-1
加到配置中- 在工程/resource目录下创建logback配置文件logback-spring.xml
与ZipKin整合
Collector:收集器组件,它主要处理从外部系统发过来的跟踪信息,将这些信息转换为Zipkin内部处理的Span格式,以支持后续的存储、分析、展示等功能
Storage:存储组件,它主要处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中。我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中。
RESTful API:API组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。
Web UI:UI组件,基于API组件实现的上层应用。通过UI组件,用户可以方便而又直观地查询和分析跟踪信息。
HTTP收集
第一步:搭建Zipkin Server
创建一个基础的SpringBoot应用,命名为zipkin-server,并修改pom.xml引入依赖
io.zipkin.java
zipkin-server
2.0.1
io.zipkin.java
zipkin-autoconfigure-ui
2.0.1 创建应用主类,使用@EnableZipkinServer注解来启动ZipkinServer,具体如下:
@EnableZipkinServer
@SpringBootApplication
public class HelloApplication {public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
修改application.properties中的配置
spring.application.name=zipkin-server
server.port=9411
创建完成后,启动工程,并访问http://localhost:9411/
,可以看到如下Zipkin管理页面:
第二步:为应用引入和配置Zipkin服务
在完成了Zipkin Server的搭建之后,还需要对应用做一些配置,以实现将跟踪信息输出到Zipkin Server。
在trace-1和trace-2的pom.xml中引入
spring-cloud-sleuth-zipkin
依赖,具体如下所示:
org.springframework.cloud
spring-cloud-sleuth-zipkin
1.3.5.RELEASE 在trace-1和trace-2的application.properties中增加Zipkin Server的配置信息。
spring.zipkin.base-url=http://localhost:9411
重启eureka-server、trace-1、trace-2,发送请求http://localhost:9101/trace-1
,可以查询出在日志中出现的跟踪信息
单击每一条记录,还能看到具体的跟踪信息
消息中间件收集
第一步:修改客户端trace-1 和trace-2
修改客户端的pom.xml,引入
org.springframework.cloud
spring-cloud-starter-sleuth
1.3.5.RELEASE
org.springframework.cloud
spring-cloud-sleuth-stream
1.3.5.RELEASE
org.springframework.cloud
spring-cloud-starter-stream-rabbit
1.3.4.RELEASE application.properties配置修改,增加消息中间件的相关配置
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456
第二步:修改zipkin-server服务端
<dependencies>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>1.3.4.RELEASE</version>
</dependency>
</dependencies>
- 重新启动eureka-server、trace-1、trace-2、zipkin-server,同时确保RabbitMQ也处于运行状态,可以在RabbitMQ的管理页面看到一个名为sleuth的交换器
通过向trace-1的接口发送几个请求http://localhost:9101/trace-1
,可以看到管理页面中的统计曲线变化
数据存储
默认情况下,Zipkin Server会将跟踪信息存储在内存中,一方面每次重启Zipkin Server都会使之前收集的跟踪信息丢失,另一方面当有大量跟踪信息时内存存储会成为瓶颈,所以通常情况下都会将跟踪信息对接到外部存储组件中去,比如使用MySQL存储
还没有评论,来说两句吧...