本文章基于spring-boot-starter-parent 2.0.6RELEASE,spring-cloud-dependencies Finchley.SR2。
在复杂的微服务架构系统中,几乎每一个前端请求都会形成一条复杂的分布式服务调用链路,在每条链路中任意一个依赖服务出现较大延迟或错误的时候都有可能导致请求的失败。这时候,对于每一个请求进行全链路调用的跟踪就变的越来越重要。
针对上述问题,Spring Cloud Sleuth为Spring Cloud提供了分布式服务跟踪的解决方案。Sleuth借用了 Dapper的术语,下面来看下Sleth使用的基础术语:
初始化 span 被称为"rootspan",该 span的 id和 trace的 ID相等。
下图展示了Span和Trace在系统中的样子:
下图展示上图中Span的父子关系:
借助之前文章中的示例,我们来集成Sleuth。
集成Sleuth只需要在user和order工程的pom文件中引入依赖即可:
org.springframework.cloud
spring-cloud-starter-sleuth
2.0.2.RELEASE
微服务应用一:User
项目启动类 AppUserApplication
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class AppUserApplication {
public static void main(String[] args) {
SpringApplication.run(AppUserApplication.class);
}
}
配置类 AppConfig
@Configuration
public class AppConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
application.yml
spring:
application:
name: user-micro #此实例注册到eureka服务端的name
sleuth:
sampler:
probability: 1.0 #request采样的数量 默认是0.1,即抽样采集10%的请求数据就,这里我们改为全部采集
server:
port: 5000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka
register-with-eureka: true
instance:
instance-id: user #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
UserController
@RestController
public class UserController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
RestTemplate restTemplate;
@RequestMapping("/getOrder.do")
@HystrixCommand(fallbackMethod = "getOrderFullBack")
public R getOrder() {
logger.info("===call trace1===");
Object object = restTemplate.getForObject("http://localhost:7000/getOrder.do", Object.class);
return R.success("操作成功", object);
}
public R getOrderFullBack() {
return R.error("系统正在维护中,请稍后重试");
}
}
微服务应用二:Order
系统启动类 AppOrderApplication
@SpringBootApplication
@EnableEurekaClient
public class AppOrderApplication {
public static void main(String[] args) {
SpringApplication.run(AppOrderApplication.class);
}
}
application.yml
server:
port: 7000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka
instance:
instance-id: order #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
spring:
application:
name: order-micro #此实例注册到eureka服务端的name
sleuth:
sampler:
probability: 1.0
OrderController
@RestController
public class OrderController {
Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping("/getOrder.do")
public Map getOrder() throws Exception {
logger.info("===call trace2===");
Map map = new HashMap();
map.put("key","order");
return map;
}
}
启动user、order、eureka等工程,浏览器访问http://localhost:5000/getOrder.do
,控制台中会发现比平时多了些信息,如红框所示:
在一次服务请求链路的调用中,会保持并传递同一个Trace ID,从而将整个分布于不同微服务进程中的请求跟踪信息串联起来。从user和order的控制台可以看出,它们的Trace ID是相同的,因为处于同一条请求链路中。
从上面可以看出,sleuth对于分布式链路的跟踪仅仅是一些数据的记录,这些数据如果我们人为去整理和分析工作量很大,而且很麻烦。所以需要借助Zipkin来帮助我们处理和分析数据。
Zipkin是Twitter的一个开源项目,它基于Google Dapper实现。可以用来收集各个服务器上请求链路的跟踪数据,并通过它提供的REST API接口来辅助查询跟踪数据以实现对分布式系统的请求链路监控,及时的发现微服务架构中存在的系统延时等问题。Zipkin还提供了一个友好的界面,帮助我们直观的搜索跟踪信息和分析请求链路明细。
zipkin官网
zipkin github地址
第一步:搭建Zipkin Server
两种方式搭建zipkin server,一种是直接下载可执行jar包,另一种是执行红框里的命令。
在zipkin2.7.x以后便不支持自定义服务器需要使用官方的版本,如上所示。如果想自己搭建zipkin server请自行百度。
注意:jdk需要1.8及以上
直接下载可执行jar,当前最新版本是zipkin-server-2.12.1-exec.jar
,命令行切换到jar包所在路径,执行java -jar zipkin-server-2.12.1-exec.jar
,从控制台中打印的图标会发现zipkin是基于springboot的,默认端口号是9411。浏览器访问http://localhost:9411
,可看到如下管理页面:
第二步:为应用引入和配置Zipkin服务
在user工程和order工程中引入zipkin依赖(因为spring-cloud-starter-zipkin
包含了spring-cloud-starter-sleuth
依赖,可以只引入zipkin这一个依赖)。
org.springframework.cloud
spring-cloud-starter-zipkin
2.0.2.RELEASE
在user工程和order工程application.yml中添加并指定zkpkin server的地址
spring:
zipkin:
base-url: http://localhost:9411 #指定Zipkin server地址
重启user和order,访问http://localhost:5000/getOrder.do
即可看到zipkin的控制台中出现了一条链路信息。
点击进去,可以看到整个链路的总耗时,以及各个服务调用的耗时等相关信息。
如果出错,也会看到详细的错误信息。把order工程停掉,再次请求http://localhost:5000/getOrder.do
会发现zipkin控制台新增一条标红的记录,点击进去可查明细。
点击控制台右侧也可以查看依赖关系
关于zipkin的各种功能,读者请自行体验。
当zipkin重启后,我们会发现分布式链路数据全部被清空了,因为zipkin server默认是将数据存储在内存当中,所以每次重启都会造成信息丢失,并且当有大量跟踪信息是我们的内存存储也会成为瓶颈。所以通常我们需要将链路信息存储到外部组件中去,比如Mysql、或者ELK平台。
下面我们使用Elasticsearch来做数据持久化
Elasticsearch下载
下载到本地后,做些简单配置(这里不再介绍),进入根目录,执行bin/elasticsearch
,windows机器上执行bin/elasticsearch.bat
。启动后在浏览器中输入http://localhost:9200/
看到如下页面说明启动成功。
zipkin server使用elasticsearch存储功能
Zipkin包含一个StorageComponent,用于存储和查询span以及依赖链接。StorageComponent包含elasticsearch、mysql、Cassandra等,可以使用这些组件作为数据存储。停掉zipkin server,改用新命令启动STORAGE_TYPE=elasticsearch ES_HOSTS=localhost:9200 java -jar zipkin-server-2.12.1-exec.jar
可以测试几次请求,然后再次重启zipkin server,发现数据没有丢失,说明zipkin和elasticsearch整合成功。
------------本文结束感谢您的阅读------------