【SpringCloud构建微服务系列】分布式链路跟踪Spring Cloud Sleuth
一、背景
随着业务的发展,系统规模越来越大,各微服务直接的调用关系也变得越来越复杂。通常一个由客户端发起的请求在后端系统中会经过多个不同的微服务调用协同产生最后的请求结果,几乎每一个前端请求都会形成一条复杂的分布式服务调用链路,对每个请求实现全链路跟踪,可以帮助我们快速发现错误根源以及监控分析每条请求链路上性能瓶颈。
针对分布式服务跟踪,Spring Cloud Sleuth提供了一套完整的解决方案。
二、原理
参考《SpringCloud微服务实战》第11章。
先查看跟踪日志了解每项的含义
2019-02-27 20:40:56.419 INFO [service-a,e79b41414a56743d,e79b41414a56743d,true] 8276 --- [nio-9001-exec-5] cn.sp.controller.ServiceController : ==<Call Service-a>==
- 第一个值service-a:记录了应用的名称,也就是spring.application.name的值。
- 第二个值e79b41414a56743d:SpringCloudSleuth生成的一个ID,叫TraceID,它用来标识一条请求链路。一条请求链路中包含一个TraceID,多个 SpanID。
- 第三个值e79b41414a56743d,SpringCloudSleuth生成的另外一个ID,叫SpanID,它表示一个基本的工作单元,比如发送一个HTTP请求。
- 第四个值true:表示是否要将该信息输出到Zipkin等服务中收集和展示。
三、编码
3.1创建一个Eureka注册中心
这个之前的文章有,故省略
3.2调用者service-a
1.创建项目引入依赖
- <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-sleuth</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-zipkin</artifactId>
- </dependency>
其实spring-cloud-starter-zipkin中已经有了sleuth的依赖,spring-cloud-starter-sleuth可以省略。
2. 启动类
@EnableEurekaClient
@SpringBootApplication
public class ServiceAApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceAApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
- ServiceController
@RestController
public class ServiceController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RestTemplate restTemplate;
@GetMapping("/service-a")
public String test(){
logger.info("==<Call Service-a>==");
return restTemplate.getForEntity("http://service-b/test",String.class).getBody();
}
}
这里的url(http://service-b/test)用的是服务名当虚拟域名而不是ip+端口号的形式,至于为什么可以访问可以查看这篇文章【Spring Cloud中restTemplate是如何通过服务名主求到具体服务的】。
4.配置文件application.yml
- spring:
- application:
- name: service-a
- zipkin:
- base-url: http://localhost:9411
- # 抽样收集的百分比,默认10%
- sleuth:
- sampler:
- probability: 1
- eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8761/eureka/
- server:
- port: 9001
3.3被调用者service-b
1.创建项目引入依赖pom文件同上
2.启动类添加注解 @EnableEurekaClient
3.ServiceController
@RestController
public class ServiceController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping("/test")
public String test(){
logger.info("==<Call Service-b>==");
return "OK";
}
}
4.配置文件application.yml
- spring:
- application:
- name: service-b
- zipkin:
- base-url: http://localhost:9411
- # 抽样收集的百分比,默认10%
- sleuth:
- sampler:
- probability: 1
- eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8761/eureka/
- server:
- port: 9002
3.4创建zipkin-server
- pom.xml
- <dependency>
- <groupId>io.zipkin.java</groupId>
- <artifactId>zipkin-server</artifactId>
- <version>2.12.2</version>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-log4j2</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- https://mvnrepository.com/artifact/io.zipkin.java/zipkin-autoconfigure-ui -->
- <dependency>
- <groupId>io.zipkin.java</groupId>
- <artifactId>zipkin-autoconfigure-ui</artifactId>
- <version>2.12.2</version>
- </dependency>
2.启动类添加注解 @EnableZipkinServer
注意: 这里我排除了log4j的依赖,因为已经有了相同的类文件启动会报错。
四、测试
- 依次启动eureka注册中,service-a,service-b,zipkin-server
- 访问http://localhost:8761/看到有两个注册实例,说明启动成功。
- 游览器访问http://localhost:9001/service-a请求服务A
如果报错日志打印java.lang.IllegalStateException: No instances available for service-b,那可能是服务B还没注册完成等会儿再试下即可。 - 正常情况会看到游览器显示 OK
服务A的日志如下:
2019-02-27 21:18:05.119 INFO [service-a,3e487761c9b13a2e,3e487761c9b13a2e,true] 8276 --- [nio-9001-exec-9] cn.sp.controller.ServiceController : ==<Call Service-a>==
服务B的日志如下:
2019-02-27 21:18:05.128 INFO [service-b,3e487761c9b13a2e,8d49352c6645c6f9,true] 13860 --- [nio-9002-exec-8] cn.sp.controller.ServiceController : ==<Call Service-b>==
- 访问http://localhost:9411/zipkin/进入可视化界面
点击查找,服务名选择service-a即可看到最近的统计数据,还可以根据条件进行筛选。
点击依赖,依赖分析就可以看到服务之前的依赖关系。
完整代码地址。
五、总结
基本是根据《SpringCloud微服务实战》这本书来的,但是中间还是踩了几个坑,比如开始报No instances available for service-b的时候我一直以为是代码哪里出了问题,浪费了很多时间。
SpringCloudSleuth除了把请求链路数据整合到Zipkin中外,还可以保存到消息队列,ELK等,还算比较强大。但是除了HTTP请求,不知道对于GRPC这样的通信方式是否也能实现链路跟踪。
查了下资料支持Grpc的,demo地址:https://github.com/tkvangorder/sleuth-grpc-sample
官方文档:https://cloud.spring.io/spring-cloud-sleuth/single/spring-cloud-sleuth.html#_grpc
【SpringCloud构建微服务系列】分布式链路跟踪Spring Cloud Sleuth的更多相关文章
- Spring cloud系列十四 分布式链路监控Spring Cloud Sleuth
1. 概述 Spring Cloud Sleuth实现对Spring cloud 分布式链路监控 本文介绍了和Sleuth相关的内容,主要内容如下: Spring Cloud Sleuth中的重要术语 ...
- 【SpringCloud构建微服务系列】微服务网关Zuul
一.为什么要用微服务网关 在微服务架构中,一般不同的微服务有不同的网络地址,而外部客户端(如手机APP)可能需要调用多个接口才能完成一次业务需求.例如一个电影购票的手机APP,可能会调用多个微服务的接 ...
- 【SpringCloud构建微服务系列】Feign的使用详解
一.简介 在微服务中,服务消费者需要请求服务生产者的接口进行消费,可以使用SpringBoot自带的RestTemplate或者HttpClient实现,但是都过于麻烦. 这时,就可以使用Feign了 ...
- 【SpringCloud构建微服务系列】使用Spring Cloud Config统一管理服务配置
一.为什么要统一管理微服务配置 对于传统的单体应用而言,常使用配置文件来管理所有配置,比如SpringBoot的application.yml文件,但是在微服务架构中全部手动修改的话很麻烦而且不易维护 ...
- 【SpringCloud构建微服务系列】学习断路器Hystrix
一.Hystrix简介 在微服务架构中经常包括多个服务层,比如A为B提供服务,B为C和D提供服务,如果A出故障了就会导致B也不可用,最终导致C和D也不可用,这就形成了雪崩效应. 所以为了应对这种情况, ...
- SpringCloud(7)服务链路追踪Spring Cloud Sleuth
1.简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可.本文主要讲述服务追踪组件zipki ...
- 史上最简单的SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)(Finchley版本)
转载请标明出处: 原文首发于:>https://www.fangzhipeng.com/springcloud/2018/08/30/sc-f9-sleuth/ 本文出自方志朋的博客 这篇文章主 ...
- 史上最简单的SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)
这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件. 注意情况: 该案例使用的spring-boot版本1.5.x,没使用2.0.x, 另外本文图3 ...
- SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)
版权声明:本文为博主原创文章,欢迎转载,转载请注明作者.原文超链接 ,博主地址:http://blog.csdn.net/forezp. http://blog.csdn.net/forezp/art ...
随机推荐
- Windows踩坑笔记之使用_tWinMain报错的解决方案
对于如下代码 #include <Windows.h> int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, ...
- [SCOI2009] 最长距离
题目描述 windy有一块矩形土地,被分为 NM 块 11 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子 ...
- checkbox 背景图片 纯CSS处理办法
CSS .table_container input[type="checkbox"] { background: #fff url(/img/blue.png); backgro ...
- Masonry库的使用
Github 简要 自动布局最重要的是约束:UI元素间关系的数学表达式.约束包括尺寸.由优先级和阈值管理的相对位置.它们是添加剂,可能导致约束冲突 .约束不足造成布局无法确定 .这两种情况都会产生异常 ...
- java的一个爬虫
进行抓取页面,我看了一下人家的教程,一般要用到htmlparser用来解析html得到一个网页的相关链接,用httpclient抓取网页数据, 下面是一我写的spider类 package com.o ...
- Java深度理解——Java字节代码的操纵
导读:Java作为业界应用最为广泛的语言之一,深得众多软件厂商和开发者的推崇,更是被包括Oracle在内的众多JCP成员积极地推动发展.但是对于 Java语言的深度理解和运用,毕竟是很少会有人涉及的话 ...
- html5--3.7 input元素(6)
html5--3.7 input元素(6) 学习要点 input元素及其属性 input元素 用来设置表单中的内容项,比如输入内容的文本框,按钮等 不仅可以布置在表单中,也可以在表单之外的元素使用 i ...
- SDK Manager中勾选项
运行SDK Manager 勾选对应版本的SDK,从这里基本可以知道一个Android版本对应着一个版本的API. 其中每个包都有这么几个文件: Documentation for Android S ...
- certificate unknown(46) - 中间证书问题排查
因为腾讯云的网站备案迟迟没有批下来,因此使用了朋友在阿里云的域名yk,我则申请了一台阿里云服务器,并将域名解析映射至该服务器.SSL证书则是在腾讯云上申请的,使用了Apache文件夹中的文件,放置在c ...
- python 去停用词
Try caching the stopwords object, as shown below. Constructing this each time you call the function ...