SpringCloudSleuth
Spring Cloud Sleuth
基础
Google Dapper
Spring Cloud Sleuth 使用
项目名称 spring-cloud-sleuth-demo
引入 maven 依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>自定义 web
@RestController public class DemoController { private Logger logger = LoggerFactory.getLogger(getClass()); @GetMapping("/hello") public String hello() { String result = "hello, world"; logger.info("{} hello() : {}", getClass().getSimpleName(), result); return result; } }application.properties 配置
# 应用名 spring.application.name=spring-cloud-sleuth访问 http://localhost:8080/hello 日志变化

日志发生的变化
当应用ClassPath 下存在org.springframework.cloud:spring-cloud-starter-sleuth时候,日志会发生调整。
整体流程
spring-cloud-starter-sleuth 会自动装配一个名为TraceFilter 组件(在 Spring WebMVC DispatcherServlet 之前),它会增加一些 slf4j MDC
MDC : Mapped Diagnostic Context
org.springframework.cloud:spring-cloud-starter-sleuth 会调整当前日志系统(slf4j)的 MDC Slf4jSpanLogger#logContinuedSpan(Span):
@Override
public void logContinuedSpan(Span span) {
MDC.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
MDC.put(Span.TRACE_ID_NAME, span.traceIdString());
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
setParentIdIfPresent(span);
log("Continued span: {}", span);
}
Spring Cloud Zipkin 使用
https://zipkin.io/
引入 maven 依赖
<!-- Zipkin 服务器 --> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-server</artifactId> <version>2.11.9</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> <version>2.1.4.RELEASE</version> </dependency> <!-- Zipkin UI --> <dependency> <groupId>io.zipkin.java</groupId> <artifactId>zipkin-autoconfigure-ui</artifactId> <version>2.11.9</version> </dependency>激活 zipkin 服务器
@SpringBootApplication @EnableZipkinServer public class SpringCloudZipkinDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudZipkinDemoApplication.class, args); } }application.properties 配置
spring.application.name=spring-cloud-zipkin-server server.port=23456浏览器访问 http://localhost:23456

Zipkin 整合 sleuth
修改 spring-cloud-sleuth-demo
HTTP 收集(HTTP 调用)
引入 zipkin 依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> <version>2.1.4.RELEASE</version> </dependency>修改 application.properties 配置
添加 zipkin 服务器配置
## Zipkin 服务器配置 zipkin.server.host=localhost zipkin.server.port=23456 # 增加 zipkin 服务器地址 spring.zipkin.base-url=\ http://${zipkin.server.host}:${zipkin.server.port}/浏览器查看
先刷新几遍 http://localhost:8080/hello,然后再到 http://localhost:23456 去查看,可以发现 zipkin 中已有有了
spring-cloud-seluth服务
Zipkin 整合Spring Cloud服务

端口信息
spring-cloud-zuul 端口:7070
person-client 端口:8080
person-service 端口:9090
Eureka Server 端口:12345
Zipkin Server 端口:23456
启动各项服务
- spring-cloud-zipkin-demo
- spring-cloud-feign-eureka
- spring-cloud-zuul-config-server
- spring-cloud-feign-demo/person-service
- spring-cloud-feign-demo/person-client
- spring-cloud-zuul-demo
注册到 eureka 上的各项服务

Sleuth 整合 eureka
spring-cloud-sleuth-demo 改造
增加 Eureka 客户端依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>激活 Eureka 客户端
@SpringBootApplication @EnableDiscoveryClient public class SpringCloudSleuthDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudSleuthDemoApplication.class, args); } // 配置 负载均衡 @LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }增加 eureka 配置,同时调整端口为 6060,避免冲突
server.port=6060 eureka.client.service-url.defaultZone=\ http://localhost:12345/eureka在 controller 中调用,调整代码连接
spring-cloud-zuul调用链路:spring-cloud-sleuth->zuul->person-client->person-service
@RestController public class DemoController { private final Logger logger = LoggerFactory.getLogger(getClass()); private final RestTemplate restTemplate; @Autowired public DemoController(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/hello") public String hello() { String result = "hello, world"; logger.info("{} hello() : {}", getClass().getSimpleName(), result); return result; } /** * 完整的调用链路 * spring-cloud-sleuth * ->zuul * ->person-client * ->person-service */ @GetMapping("/to/zuul/person-client/person/find/all") public Object toZuul() { // spring-cloud-zuul: 7070 logger.info("spring-cloud-sleuth#toZuul"); String url = "http://spring-cloud-zuul/person-client/person/find/all"; return restTemplate.getForObject(url, Object.class); } }eureka 注册成功

测试结果
http://localhost:6060//to/zuul/person-client/person/find/all

Zipkin 整合其他服务
涉及服务
- spring-cloud-zuul
- person-client
- person-service
整合步骤
添加 maven 依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> <version>2.1.4.RELEASE</version> </dependency>配置 zipkin 服务地址
## Zipkin 服务器配置 zipkin.server.host = localhost zipkin.server.port = 23456 ## 增加 ZipKin 服务器地址 spring.zipkin.base-url = \ http://${zipkin.server.host}:${zipkin.server.port}/
整合结果

完整调用链路

Spring Cloud Stream 收集(消息)
调整spring-cloud-zipkin-server 通过 Stream 来收集
增加 Maven 依赖
<!-- Zipkin 服务器通过Stream 收集跟踪信息 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<!-- 使用 Kafka 作为 Stream 服务器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
激活 Zipkin Stream
package com.gupao.springcloudzipkinserverdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.sleuth.zipkin.stream.EnableZipkinStreamServer;
import zipkin.server.EnableZipkinServer;
@SpringBootApplication
//@EnableZipkinServer
@EnableZipkinStreamServer
public class SpringCloudZipkinServerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudZipkinServerDemoApplication.class, args);
}
}
启动 Zookeeper
启动 Kafka 服务器
启动spring-cloud-zipkin-server
调整 spring-cloud-zuul
增加依赖
<!-- 添加 sleuth Stream 收集方式 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<!-- Kafka Binder -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
注意把前面 HTTP 上报URL配置注释:
### 增加 ZipKin 服务器地址 #spring.zipkin.base-url = \ # http://${zipkin.server.host}:${zipkin.server.port}/
问答部分
只有第一个被访问的应用的pom引用了spring-cloud-starter-sleuth包么?后面的应用spanid是怎么生成的?上报是汇集到一起上报么?
答:每个应用都需要依赖
spring-cloud-starter-sleuth。SpanId 是当前应用生成的,Trace ID 是有上个应用传递过来(Spring Cloud 通过请求头Headers)sleuth配合zipkin主要解决的是分布式系统下的请求的链路跟踪,这么理解没错吧?
答:可以这么理解,问题排查、性能、调用链路跟踪
sleuth 与 eureka 没关联吧?
答:没有直接关系,Sleuth 可以利用 Eureka 做服务发现
生产上类sleuth的log日志应该看哪些资料?opentsdb,也有调用链路等相关信息么?
答:OpenTsdb 主要是存储 JSON 格式,存放Metrics 信息
排查问题是根据traceid来查找有所日志吧
答:可以通过TraceId 查找调用链路,通过 Span Id 定位在什么环节
整合显示是sleuth做的,zipkin用来收集信息对吧?
答:zipkin 是一种用整合方式
问个题外话,两个系统对接需要通过json进行数据传输,但是两个系统之间的json数据格式是不同的,有没有好一点的开源项目可以解决这个问题,类似xslt转换xml的方式。
答:A -> B, data1 , B -> A data2, 接受方使用Map。JSON Path
{"id":1, abc:{ "name":"xiaomage", "age":32 } }