随着业务发展,系统拆分致使系统调用链路愈发复杂一个前端请求可能最终须要调用不少次后端服务才能完成,当整个请求陷入性能瓶颈或不可用时,咱们是没法得知该请求是由某个或某些后端服务引发的,这时就须要解决如何快读定位服务故障点,以对症下药。因而就有了分布式系统调用跟踪的诞生。 Spring Cloud Sleuth 也为咱们提供了一套完整的解决方案。在本文中,咱们将详细介绍如何使用 Spring Cloud Sleuth + Zipkin 来为咱们的微服务架构增长分布式服务跟踪的能力。html
Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud, borrowing heavily from Dapper, Zipkin and HTrace. For most users Sleuth should be invisible, and all your interactions with external systems should be instrumented automatically. You can capture data simply in logs, or by sending it to a remote collector service.前端
Spring Cloud Sleuth是Spring Cloud实施分布式跟踪解决方案,大量借用Dapper,Zipkin和HTrace。 对于大多数用户来讲,侦探应该是隐形的,而且全部与外部系统的交互都应该自动进行检测。 您能够简单地在日志中捕获数据,也能够将数据发送到远程收集器服务。java
SpringCloudSleuth 借用了 Dapper 的术语:mysql
Spring Cloud Sleuth 为服务之间调用提供链路追踪。经过 Sleuth 能够很清楚的了解到一个服务请求通过了哪些服务,每一个服务处理花费了多长。从而让咱们能够很方便的理清各微服务间的调用关系。此外 Sleuth 能够帮助咱们:git
- 耗时分析:经过 Sleuth 能够很方便的了解到每一个采样请求的耗时,从而分析出哪些服务调用比较耗时;
- 可视化错误:对于程序未捕捉的异常,能够经过集成 Zipkin 服务界面上看到;
- 链路优化:对于调用比较频繁的服务,能够针对这些服务实施一些优化措施。
Spring Cloud Sleuth 能够结合 Zipkin,将信息发送到 Zipkin,利用 Zipkin 的存储来存储信息,利用 Zipkin UI 来展现数据。github
这是 Spring Cloud Sleuth 的概念图: web
只须要在pom.xml的dependencies中添加以下依赖,就能够为应用整合sleuth:spring
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
整合完成以后,启动项目,调用一个请求(我人为的关闭了应用要调用的另外一个微服务,致使了请求失败),这是看控制台日志:sql
2019-10-29 16:28:57.417 INFO [study01,,,] 5830 --- [-192.168.31.101] o.s.web.servlet.DispatcherServlet : Completed initialization in 27 ms 2019-10-29 16:28:57.430 INFO [study01,,,] 5830 --- [-192.168.31.101] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2019-10-29 16:28:57.433 INFO [study01,,,] 5830 --- [-192.168.31.101] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2019-10-29 16:28:58.520 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.e.s.feignClient.CommentFeignClient : [CommentFeignClient#find] ---> GET http://study02/find HTTP/1.1 2019-10-29 16:28:58.520 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.e.s.feignClient.CommentFeignClient : [CommentFeignClient#find] ---> END HTTP (0-byte body) 2019-10-29 16:28:58.520 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.s.i.w.c.f.TraceLoadBalancerFeignClient : Before send 2019-10-29 16:28:58.646 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.netflix.config.ChainedDynamicProperty : Flipping property: study02.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647 2019-10-29 16:28:58.661 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.netflix.loadbalancer.BaseLoadBalancer : Client: study02 instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=study02,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null 2019-10-29 16:28:58.667 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater 2019-10-29 16:28:58.683 INFO [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client study02 initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=study02,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@591b62cf 2019-10-29 16:28:58.707 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] o.s.c.s.i.a.ContextRefreshedListener : Context successfully refreshed 2019-10-29 16:28:58.755 DEBUG [study01,42d9bd786504f775,42d9bd786504f775,false] 5530 --- [nio-8881-exec-1] c.s.i.w.c.f.TraceLoadBalancerFeignClient : Exception thrown
能够看见日志的形式和以前不太同样了,首先启动日志里面多了个中括号:[study01,,,];而当应用请求报异常的时候,中括号中有了这些数据:[study01,42d9bd786504f775,42d9bd786504f775,false] study01是应用名称,42d9bd786504f775是 trace ID,42d9bd786504f775是span ID,false表示是否是要把这条数据上传给zipkin。这时,就能够经过日志分析应用哪里出了问题、哪一个阶段出了问题。后端
**PS:**能够在应用中添加以下配置:
logging: level: org.springframework.cloud.sleuth: debug
这段配置的用处是让sleuth打印更多的日志,从而进一步帮助咱们分析错误【我上面粘出的日志就是添加配置以后的结果】。
Zipkin 是 Twitter 的开源分布式跟踪系统,它基于 Google Dapper 实现,它致力于收集服务的时序数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展示。
curl -sSL https://zipkin.io/quickstart.sh | bash -s
访问以下地址下载: https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec
下载完成以后,在下载的jar所在目录,执行java -jar *****.jar
命令便可启动Zipkin Server 访问http://localhost:9411 便可看到Zipkin Server的首页。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
PS:当使用了spring-cloud-starter-zipkin以后,前面添加spring-cloud-starter-sleuth就不须要了,由于前者包含了后者。
spring: zipkin: base-url: http://localhost:9411/ sleuth: sampler: # 抽样率,默认是0.1(90%的数据会被丢弃) # 这边为了测试方便,将其设置为1.0,即全部的数据都会上报给zipkin probability: 1.0
启动项目,产生请求以后,打开zipkin控制台,能够刚刚请求的信息(按耗时降序排列):
点击能够查看请求的详情:
这张图中,Server Start表示的是Server Received;Server Finish表示的是Server Sent。 由于客户端发生在浏览器上,而浏览器并无整合zipkin,因此zipkin中没有Client Sent和Client Received数据。
前面搭建Zipkin是基于内存的,若是Zipkin发生重启的话,数据就会丢失,这种方式是不适用于生产的,因此咱们须要实现数据持久化。 Zipkin给出三种数据持久化方法:
相关的官方文档:https://github.com/openzipkin/zipkin#storage-component , 本文将介绍Elasticsearch实现Zipkin数据持久化
咱们须要下载什么版本的Elasticsearch呢,官方文档给出了建议,5-7版本均可以使用(本文使用的是Elasticsearch6.8.2,由于Elasticsearch7开始后须要jdk11支持):
The Elasticsearch component uses Elasticsearch 5+ features, but is tested against Elasticsearch 6-7.x.
下载完成后,解压缩软件包,进入bin目录,执行 ./elasticsearch
便可启动Elasticsearch:
访问http://localhost:9200/
,出现以下页面,说明Elasticsearch启动成功:
zipkin提供了不少的环境变量,配置环境变量就能够将数据存储进Elasticsearch。
- STORAGE_TYPE: 指定存储类型,可选项为:mysql, cassandra, elasticsearch
- ES_HOSTS:Elasticsearch地址,多个使用,分隔,默认http://localhost:9200
- ES_PIPELINE:指定span被索引以前的pipeline(Elasticsearch的概念)
- ES_TIMEOUT:链接Elasticsearch的超时时间,单位是毫秒;默认10000(10秒)
- ES_INDEX:zipkin所使用的索引前缀(zipkin会天天创建索引),默认zipkin
- ES_DATE_SEPARATOR:zipkin创建索引的日期分隔符,默认是-
- ES_INDEX_SHARDS:shard(Elasticsearch的概念)个数,默认5
- ES_INDEX_REPLICAS:副本(Elasticsearch的概念)个数,默认1
- ES_USERNAME/ES_PASSWORD:Elasticsearch帐号密码
- ES_HTTP_LOGGING:控制Elasticsearch Api的日志级别,可选项为BASIC、HEADERS、BODY
更多环境变量参照:https://github.com/openzipkin/zipkin/tree/master/zipkin-server#environment-variables
执行下面代码从新启动zipkin:
STORAGE_TYPE=elasticsearch ES_HOSTS=localhost:9200 java -jar zipkin-server-2.12.9-exec.jar
产生请求以后,访问http://localhost:9411/zipkin/,能够看见刚刚请求的数据:
停调zipkin,而后再次启动,访问http://localhost:9411/zipkin/,能够看见数据依然存在:
说明此时,数据已经实现了持久化。
从官方文档能够看出,使用Elasticsearch进行zipkin数据持久化以后,Zipkin的依赖关系分析功能没法使用了。
Note: This store requires a spark job to aggregate dependency links. 咱们须要整合zipkin-dependencies来实现依赖关系图功能。zipkin-dependencies是zipkin的一个子项目,启动很是的简单。
下载: curl -sSL https://zipkin.io/quickstart.sh | bash -s io.zipkin.dependencies:zipkin-dependencies:LATEST zipkin-dependencies.jar 启动: STORAGE_TYPE=elasticsearch ES_HOSTS=localhost:9200 java -jar zipkin-dependencies.jar
- STORAGE_TYPE: 指定存储类型,可选项为:mysql, cassandra, elasticsearch
- ES_HOSTS:Elasticsearch地址,多个使用,分隔,默认http://localhost:9200
- ES_INDEX:zipkin所使用的索引前缀(zipkin会天天创建索引),默认zipkin
- ES_DATE_SEPARATOR:zipkin创建索引的日期分隔符,默认是-
- ES_NODES_WAN_ONLY:若是设为true,则表示仅使用ES_HOSTS所设置的值,默认为false。当Elasticsearch集群运行在Docker中时,可将该环境变量设为true。
这边只须要把项目启动,就能够展现依赖关系图了,这里就再也不演示了。 **注意:**zipkin-dependencies启动以后会自动中止,因此建议使用定时任务让操做系统定时启动zipkin-dependencies。
分析昨天的数据(OS/X下的命令) STORAGE_TYPE=elasticsearch java -jar zipkin-dependencies.jar 'date -uv-ld + %F' 分析昨天的数据(Linux下的命令) STORAGE_TYPE=elasticsearch java -jar zipkin-dependencies.jar 'date -u -d '1 day ago' + %F' 分析指定日期的数据 STORAGE_TYPE=elasticsearch java -jar zipkin-dependencies.jar 2019-10-29
原文出处:https://www.cnblogs.com/fx-blog/p/11757124.html