1. 简介
Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可。
------ 摘自方志朋
2. 服务追踪分析
微服务架构上通过业务来划分服务的,通过REST调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。
3. sleuth与Zipkin关系?
spring cloud提供了spring-cloud-sleuth-zipkin来方便集成zipkin实现(指的是Zipkin Client,而不是Zipkin服务器),该jar包可以通过spring-cloud-starter-zipkin依赖来引入。
4. Zipkin是什么
Zipkin分布式跟踪系统;它可以帮助收集时间数据,解决在microservice架构下的延迟问题;它管理这些数据的收集和查找;Zipkin的设计是基于谷歌的Google Dapper论文。
每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序;如果想解决延迟问题,可以过滤或者排序所有的跟踪请求,并且可以查看每个跟踪请求占总跟踪时间的百分比。
5. 为什么使用Zipkin
随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题。
上代码之前
先安装zipkin。如果你有java 8或更高版本,上手最快的方法是把新版本作为一个独立的可执行jar,Zipkin使用springboot来构建的。下面是zipkin的下载地址,选择zipkin-server-X.XX.X-exec.jar格式的来下载
https://dl.bintray.com/openzipkin/maven/io/zipkin/zipkin-server/
下载完后在保证已经配置好java jdk的情况下,控制台运行
java -jar zipkin-server-X.XX.X-exec.jar
服务就能够正常启动了
然后在浏览器地址栏输入
[http://localhost:9411
就能够进入zipkin的可视化管理界面了
开始上代码
首先我要重现两个项目之间的一个依赖关系,这里我创建三个项目,一个是Eureka Server,一个是Eureka Client,一个是 Feign
第一个项目 Eureka Server
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
配置文件
server.port=8762 spring.application.name=eureka-server eureka.client.service-url.defaultZone=http://localhost:8762/eureka
启动类 ```java @EnableEurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
第二个项目 Eureka Client
pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
配置文件
# 项目端口号 server.port=8777 # 应用名称 spring.application.name=eureka-client # 注册中心的url地址 eureka.client.service-url.defaultZone=http://10.2.1.66:8762/eureka # zipkin的地址 spring.zipkin.base-url=http://localhost:9411
入口类
@EnableEurekaClient @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
创建一个Controller类,用于测试
@RestController public class HelloController { /** * 将配置文件中server.port属性 注入到port变量中 * 可以通过观察端口的不同,判断当前走的是哪个项目 */ @Value("${server.port}") private String port; @GetMapping("/hi") public String hi(){ return "hello world"+port; } }
第三个项目 Feign
导入pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
配置文件
server.port=8782 spring.application.name=feign eureka.client.service-url.defaultZone=http://localhost:8762/eureka # 开启 断路器 功能 feign.hystrix.enabled=true spring.zipkin.base-url=http://localhost:9411
入口类
@EnableFeignClients @EnableEurekaClient @SpringBootApplication public class FeginApplication { public static void main(String[] args) { SpringApplication.run(FeginApplication.class, args); } }
创建一个Service接口
// 指定远程调用的服务名称/应用名称 // fallback 当发生长时间未响应的情况,就会执行HiServiceBack中的内容 @FeignClient(value = "eureka-client",fallback = HiServiceBack.class) public interface IHiService { @GetMapping("/hi") String sayHi(); }
创建一个HiServiceBack类,服务器无法访问时会访问这个这个类
@Component public class HiServiceBack implements IHiService { @Override public String sayHi() { return "sorry,connect failed"; } }
创建一个controller类,用于测试
@RestController public class HiController { // 这里hiService可能会报错,但这并不是错误,是编译器有毛病! @Autowired private IHiService hiService; @GetMapping("/hello") public String hello(){ return hiService.sayHi(); } }
三个项目部署完成后 启动运行,再到浏览器去访问刚才写的测试接口
当然,访问的时候端口要写feign服务器的,因为这里要通过feign服务器实现负载均衡去访问server client
最后,我们进入localhost:9411,点击依赖,就会出现一个依赖关系
总结:随着服务的越来越多,对调用链的分析会越来越复杂,所以就需要使用到Spring Cloud Sleuth来解决这个问题