目录
一、前言
二、分布式链路调用问题
三、链路追踪中的几个概念
3.1 什么是链路追踪
3.2 常用的链路追踪技术
3.3 链路追踪的几个术语
3.3.1 span
?编辑
3.3.2 trace
3.3.3 Annotation
四、sluth与zipkin概述
4.1 sluth介绍
4.1.1 sluth是什么
4.1.2 sluth核心功能
4.1.3 sluth工作原理
4.2 zipkin介绍
4.2.1 zipkin是什么
4.2.2 zipkin工作原理与核心组件
4.3 sluth与zipkin的关系
五、微服务集成Sleuth
5.1 Sleuth集成过程
5.1.1 导入依赖
5.1.2 添加注解
5.1.3 参数说明
六、微服务集成sleuth + zipkin
6.1 部署zipkin服务端
6.1.2 访问UI界面
6.2 zipkin数据持久化
6.2.1 获取zipkin的建表sql
6.2.2 重启zipkin服务
6.3 springcloud客户端集成zipkin
6.3.1 导入zipkin依赖
6.3.2 添加配置文件
6.3.3 重启服务并触发接口调用
七、写在文末
一、前言
在springcloud技术栈构建的微服务架构体系中,一旦微服务数量越来越多,服务之间的调用链路也必然越来越复杂,遇到问题时,排查难度也会相应增加。
二、分布式链路调用问题
如下图所示,为模拟一个微服务架构的系统在真实线上部署的场景,客户端发出的一个请求,通过网关之后,在内部处理请求时,可能经历了非常复杂的互相调用,试想,现在某个链路突然发生异常,对于开发人员来说,是不是有点摸不着头脑。
以上只是众多的微服务调用链路中相对比较简单的一种,通常来说,在分布式调用中,一个由客户端发起的请求,在后端系统中会经过多个不同的微服务调用来协同产生最后的请求结果。
在复杂的微服务架构系统中,几乎每一个请求都会形成一条复杂的分布式服务调用链路。在每条链路中,任何一个依赖服务出现延迟过高,或错误时都有可能造成请求最后的失败。这时对于每个请求全链路调用的跟踪就变得非常重要。
通过实现对请求调用的跟踪,可以帮助开发人员快速的定位错误根源,以及监控分析每条请求链路上的性能瓶颈等。
在开源的分布式链路追踪解决方案中,以springcloud生态来说,针对微服务链路追踪这个问题,Spring Cloud Sleuth提供了一套完整的解决方案。
三、链路追踪中的几个概念
3.1 什么是链路追踪
链路追踪一词最早在2010年提出,由谷歌发表的一篇关于大规模分布式系统跟踪的论述,介绍了谷歌自研的分布式链路追踪的实现原理。
侠义上理解链路追踪,就是指一次任务从开始到结束,期间调用的所有系统以及耗时(时间跨度)都可以完整的记录下来。
广义上讲,链路追踪是指在分布式系统中,将一次请求的处理过程进行记录并聚合展示的一种方法。目的是将一次分布式请求的调用情况集中在一处展示,如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等。这样就可以轻松了解一个请求在系统中的完整生命周期,包括经过的服务、调用的操作以及每个操作的延迟等。
通过链路追踪,可以更好地理解系统的性能瓶颈、找出问题的根源以及优化系统的性能。
3.2 常用的链路追踪技术
目前,链路追踪方案像Google的Dapper,阿里的鹰眼,大众点评的CAT,Twitter的Zipkin,LINE的pinpoint,国产的skywalking等。市面上的全链路监控理论模型大多都是借鉴Google Dapper论文,这里列举下面几种:
- cat:由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控。集成方案是通过代码埋点的方式实现监控。比如:拦截器,过滤器等。对业务代码具有一定的侵入性,集成成本较大,风险较高;
- Zipkin :由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微服务架构中的延迟问题,包括:数据的收集、存储、查找和展现,通常结合springcloud-sleuth一起使用比较简单,集成方便,但是功能相对简单;
- Pinpoint :一款对Java编写的大规模分布式系统的APM工具,由韩国人开源的分布式跟踪组件,其底层基于字节码的注入进行调用链的分析,以及应用监控分析工具,其特点是支持多种插件,UI功能强大,接入端无代码前任;
- Skywalking :国产的优秀APM组件,是一个对JAVA分布式应用程序集群的业务运行情况进行追踪、告警和分析的系统,基于字节码注入调用链分析,以及应用监控分析工具,特点是支持多种插件,UI功能强大,接入端无代码侵入,目前已加入apache孵化;
- sleuth,由springcloud提供的分布式系统中链路追踪的解决方案;
下面结合两种使用较多的链路追踪工具zipkin和Skywalking 进行对比说明
类型 | zipkin | SKYwalking |
基本原理 | 拦截请求,发送(HTTP,mq)数据至zipkin服务 | java探针,字节码增强 |
接入方式 | 基于linkerd或者sleuth方式,引入配置即可 | Java agent字节码 |
支持OpenTracing | 是 | 是 |
颗粒度 | 接口级(类级别) | 方法级 |
存储 | ES,mysql,Cassandra,内存 | ES,H2,TIDB |
agent到collector的协议 | http,MQ | http,gRPC |
3.3 链路追踪的几个术语
在链路追踪的解决方案中,不管是哪一种,基本上各个组件底层都使用了相同的规范,其中涉及到下面几个非常重要的术语。
3.3.1 span
span代表一组基本的工作单元,一次单独的调用链可称为一个span。通俗理解,span就是一次请求信息,当发送一个远程调用时就会产生一个Span,Span 由一个64位ID唯一标识的。
举例来说,为统计一个请求中各处理单元的延迟,当请求到达服务的各个组件时,通过一个唯一标识(SpanId)来标记它的开始、具体过程和结束。通过SpanId的开始和结束时间戳,就能统计该span的调用时间,除此之外,我们还可以获取如事件的名称。请求信息等元数据。
如下,图中一个矩形框就是一个 Span,前端从发出请求到收到回复就是一个 Span。
3.3.2 trace
由一组TraceId相同的Span串联形成的一个树状结构。一个trace可认为是一次完整的链路,内部包含多个span,trace和span之间是一对多的关系。而span与span之间存在父子级关系。
为实现请求跟踪,当请求到达分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的标识(即TraceId),同时在分布式系统内部流转的时候,框架始终保持传递该唯一值,直到整个请求的返回。那么我们就可以使用该唯一标识将所有的请求串联起来,形成一条完整的请求链路。
举个例子:客户端调用服务 A 、服务 B 、服务 C 、服务 F,而每个服务例如 C 就是一个 Span,如果在服务 C 中另起线程调用了 D,那么 D 就是 C 的子 Span,如果在服务 D 中另起线程调用了 E,那么 E 就是 D 的子 Span,这个 C -> D -> E 的链路就是一条 Trace。如果链路追踪系统做好了,链路数据有了,借助前端解析和渲染工具,可以达到下图中的效果:
3.3.3 Annotation
Annotation 用于记录一段时间内的事件,内部使用的重要注释:
- cs(Client Send),客户端发起一个请求,这个 annotation 描述了这个 span 的开始;
- sr(Server Received),服务端获得请求并准备开始处理它,如果 sr 减去 cs 时间戳便可得到网络延迟;
- ss(Server Send),请求处理完成(当请求返回客户端),如果 ss 减去 sr 时间戳便可得到服务端处理请求需要的时间;
- cr(Client Reveived),表示 span 结束,客户端成功接收到服务端的回复,如果 cr 减去 cs 时间戳便可得到客户端从服务端获取回复的所有所需时间;
四、sluth与zipkin概述
4.1 sluth介绍
4.1.1 sluth是什么
Spring Cloud 微服务治理框架中的一个组件,专门用于记录链路数据的开源组件,官网地址
4.1.2 sluth核心功能
sluth提供的核心功能主要如下:
- 链路追踪:通过 Sleuth 可以很清楚的看出一个请求都经过了那些服务,可以很方便的理清服务间的调用关系等;
- 性能分析:通过 Sleuth 可以很方便的看出每个采样请求的耗时,分析哪些服务调用比较耗时,当服务调用的耗时随着请求量的增大而增大时, 可以对服务的扩容提供一定的提醒;
- 数据分析,优化链路:对于频繁调用一个服务,或并行调用等,可以针对业务做一些优化措施;
- 可视化错误:对于程序未捕获的异常,可以配合 Zipkin 查看;
4.1.3 sluth工作原理
下面这张图详细说明了sleuth在工作过程中其内部的运行原理,理解了这张图的原理,不仅明白了sleuth是如何运行的,也对链路追踪中的几个概念也会有更深刻的理解。
关于这张图的调用过程做如下说明:
- 从左到右,展示了客户端从发送一个请求,到最终请求响应结果的完整链路;
- 如果想知道一个接口在哪个环节出现了问题,就必须清楚该接口调用了哪些服务,以及调用的顺序,如果把这些服务串起来,看起来就像链条一样,我们称之为调用链;
- 想要实现调用链,就要为每次调用做个标识,然后将服务按标识大小排列,可以更清晰地看出调用顺序,我们暂且将该标识命名为 spanid;
- 实际场景中,我们需要知道某次请求调用的情况,所以只有spanid还不够,得为每次请求做个唯一标识,这样才能根据标识查出本次请求调用的所有服务,而这个标识我们命名为 traceid;
- 现在根据 spanid 可以轻易地知道被调用服务的先后顺序,但无法体现调用的层级关系,正如下图所示,多个服务可能是逐级调用的链条,也可能是同时被同一个服务调用;
- 所以应该每次都记录下是谁调用的,我们用 parentid 作为这个标识的名字;
- 到现在,已经知道调用顺序和层级关系了,但是接口出现问题后,还是不能找到出问题的环节,如果某个服务有问题,那个被调用执行的服务一定耗时很长,要想计算出耗时,上述的三个标识还不够,还需要加上时间戳,时间戳可以更精细一点,精确到微秒级;
其实 span 内除了记录这几个参数之外,还可以记录一些其他信息,比如发起调用服务名称、被调服务名称、返回结果、IP、调用服务的名称等,最后,我们再把相同 parentid 的 span 信息合成一个大的 span 块,就完成了一个完整的调用链。
4.2 zipkin介绍
4.2.1 zipkin是什么
zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper的论文设计而来,由 Twitter 公司开发贡献。它有助于收集对服务架构中的延迟问题进行故障排除所需的计时数据。功能包括收集和查找这些数据。
zipkin是一个开放源代码分布式的跟踪系统,它可以帮助收集服务调用中的时间数据,以解决微服务架构中的延迟问题。具体来说,包括数据收集、存储、查找和展现。
当微服务接入zipkin之后,每个服务向zipkin报告计时数据,zipkin会根据调用关系通过Zipkin UI生成依赖关系图,展示多少跟踪请求经过了哪些服务,该系统让开发者可通过一个web前端轻松地收集和分析数据,可非常方便的监测系统中存在的瓶颈。
下面是一张关于zipkin的原理图,从图中不难发现,在真实的环境中,zipkin主要是承担收集各个服务上报过来的信息,比如日志、服务链路等数据,经过内部的处理之后,通过ui界面进行展现。
4.2.2 zipkin工作原理与核心组件
下面是zipkin的工作原理图
或者通过下面这张运行原理图可以以全局的视角来了解zipkin
从上面的图中,可以发现zipkin在运行过程中,其核心组件主要包括下面几种:
Collector:信息收集器
主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为Zipkin内部处理的Span格式,以支持后续的存储、分析、展示等功能。
Storage:数据存储组件
主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中,我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到 数据库或es 中。
RESTful API:API组件
主要用于提供外部访问接口,比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。
Web UI:UI组件
基于API组件实现的上层应用。通过UI组件用户可以方便而有直观地查询和分析跟踪信息。
小结:
1)Zipkin 分两端,一个是 Zipkin 服务端,一个是 Zipkin 客户端,客户端也就是微服务应用;
2)客户端会配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端;
3)发送的方式有两种,一种是消息总线的方式如 RabbitMQ 发送,还有一种是 HTTP 报文的方式发送;
4.3 sluth与zipkin的关系
通过上面的介绍我们了解到,Sleuth是将每个请求从开始调用到结束过程中的每一步都进行记录, 但这些信息都是分散存在的,通过以日志格式输出出来,真正进行问题分析定位时并不方便,此时就需要有一个工具可以将这些分散的信息进行收集和汇总,并且能显示可视化结果,便于分析和定位。
有了zipkin之后,sleuth的只需要把链路追踪的元数据信息上报给zipkin,由zipkin进行存储并将链路信息以可视化的方式进行呈现。
五、微服务集成Sleuth
sleuth可以单独在springboot项目中使用,也可以在springcloud、dubbo中进行集成,下面介绍sleuth最简单的集成方式。
5.1 Sleuth集成过程
文档地址:官方文档地址
git地址:sleuth git地址
5.1.1 导入依赖
maven中导入sleuth依赖
<!-- spring cloud sleuth 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
5.1.2 添加注解
以之前整合的一个springcloud微服务为例进行说明,最简单的集成方式是,只需要在需要进行链路追踪的类上面添加 @Slf4j注解即可,如下,服务的调用链路为:order -> user,我们分别在需要调用的类上面添加注解;
用户微服务中添加注解,在方法的关键入口添加日志输出,默认sleuth追踪info级别的日志
@RestController @RequestMapping("/user") @Slf4j public class UserController { @Autowired private UserService userService; //http:localhost:9002/user/getById?id=001 @GetMapping("/getById") public User getById(@RequestParam String id) { log.info("根据ID获取用户信息"); return userService.getById(id); } }
@Slf4j @Service public class UserServiceImpl implements UserService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private UserMapper userMapper; @Override public User getById(String id) { log.info("[用户服务] 基于 id 查询用户信息:{}", id); String key = "sw:users:" + id; Object json = redisTemplate.opsForValue().get(key); if (json != null) { log.info("[用户服务] redis 中查询到用户信息:key={}, json={}", key, json); return JSON.parseObject(json.toString(), User.class); } User user = userMapper.getById(id); if (user != null) { log.info("[用户服务] redis 中不存在,从数据库查到数据并缓存:{}", user); redisTemplate.opsForValue().set(key, user, 2, TimeUnit.HOURS); return user; } log.warn("[用户服务] 基于 id 查询用户失败,用户不存在:{}", id); return null; } }
order微服务中添加注解
@RequestMapping("/order") @RestController @Slf4j public class OrderController { @Autowired private OrderService orderService; //localhost:9003/order/getById?id=001 @GetMapping("/getById") public Object getById(@RequestParam String id) { log.info("根据ID获取订单"); return orderService.getById(id); } }
@Slf4j @Service public class OrderServiceImpl implements OrderService { @Autowired private UserFeignService userFeignService; @Override public Map getById(String id) { log.info("[订单服务] 基于 id 查询订单详情:{}", id); Map map = new HashMap(); Order order = new Order(); order.setOrderId("0002"); order.setProductId("0001"); order.setProductName("小米手机"); map.put("order",order); User user = userFeignService.getById("001"); map.put("user",user); return map; } }
重启两个微服务模块,然后调用一下接口
5.1.3 参数说明
接口调用成功后,我们观察控制台输出日志信息,order模块输出日志信息如下:
user模块输出的日志信息如下:
关于日志信息,做如下几点说明:
- 第一个值,spring.application.name 的值;
- 第二个值,sleuth生成的一个ID,即traceId,用来标识一条请求链路,一条请求链路中包含一个traceId,多个spanId;
- 第三个值,spanId,基本工作单元,获取元数据,比如发送一个http;
- 第四个值,true/false,表示信息输出到zipkin中收集和展示;
六、微服务集成sleuth + zipkin
通过上文了解到,zipkin是一款用于做实时链路数据追踪的应用,通过可视化的方式展现从服务中上报的日志等链路追踪数据,便于问题的排查定位和分析,更加的人性化。
通常,以springcloud技术栈的微服务中,通常是将sleuth 搭配zipkin一起使用。当然也可以单独在springboo工程中接入zipkin。
6.1 部署zipkin服务端
zipkin服务端是一个独立的可执行的 jar 包,jar包下载地址:
1、官网下载,OpenZipkin · A distributed tracing system
2、ftp下载,zipkin各版本下载地址
这里我下载 2.22.1的版本的jar包
下载之后,不管是本地还是在linux服务器上,最简单的方式,直接使用下面的命令启动即可
java -jar zipkin-server-2.20.1-exec.jar
6.1.2 访问UI界面
服务启动之后,通过9411端口可以直接访问zipkin的web-ui界面,如下图所示,后面当微服务接入zipkin之后,一旦发生服务间的调用将会展示出调用链路相关信息
6.2 zipkin数据持久化
Zipkin 默认将监控数据存储在内存中,很显然,如果 Zipkin 挂掉或重启的话,监控数据就会丢失。所以生产中,肯定是不能直接这样使用,需要对Zipkin的监控数据进行持久化存储。zipkin提供了多种数据持久化存储的方式:
- 内存(默认);
- mysql(推荐);
- es(推荐);
- Cassandra;
下面以mysql为例进行说明
6.2.1 获取zipkin的建表sql
脚本下载地址在 github zipkin项目里的 zipkin-storage/mysql-v1/src/main/resounce 目录下
mysql脚本地址
为例方便使用,下面贴出完整的sql
-- -- Copyright 2015-2019 The OpenZipkin Authors -- -- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except -- in compliance with the License. You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software distributed under the License -- is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -- or implied. See the License for the specific language governing permissions and limitations under -- the License. -- CREATE TABLE IF NOT EXISTS zipkin_spans ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL, `id` BIGINT NOT NULL, `name` VARCHAR(255) NOT NULL, `remote_service_name` VARCHAR(255), `parent_id` BIGINT, `debug` BIT(1), `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL', `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query', PRIMARY KEY (`trace_id_high`, `trace_id`, `id`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds'; ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames'; ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames'; ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range'; CREATE TABLE IF NOT EXISTS zipkin_annotations ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id', `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id', `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1', `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB', `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation', `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp', `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address', `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds'; ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames'; ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values'; ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job'; CREATE TABLE IF NOT EXISTS zipkin_dependencies ( `day` DATE NOT NULL, `parent` VARCHAR(255) NOT NULL, `child` VARCHAR(255) NOT NULL, `call_count` BIGINT, `error_count` BIGINT, PRIMARY KEY (`day`, `parent`, `child`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
创建一个数据库,名为zipkin,然后执行上面的sql创建表
6.2.2 重启zipkin服务
使用下面的命令重新启动zipkin服务
java -jar zipkin-server-2.22.1-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=IP地址 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=密码
启动之后再次访问,仍然可以正常访问ui页面
6.3 springcloud客户端集成zipkin
上面的环境准备好之后,相当于是搭建了zikpkin的服务端,接下来就可以在springcloud微服务工程中(客户端)集成zpikin,将客户端的服务调用链路信息上报zipkin了,参考下面的操作步骤
6.3.1 导入zipkin依赖
sleuth的依赖仍然保留,同时添加zipkin的依赖
<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>
6.3.2 添加配置文件
在工程的配置文件中添加如下关于zipkin和sleuth的配置信息,如果是云服务器,需要提前开通9411的防火墙端口
server: port: 9002 spring: application: name: user-service zipkin: base-url: http://127.0.0.1:9411 sleuth: sampler: probability: 1 cloud: nacos: discovery: server-addr: nacos地址:8848
6.3.3 重启服务并触发接口调用
确保zipkin服务已经启动,然后启动user和order两个服务,并调用下面的获取订单接口
调用成功后,在zipkin的ui界面上就能看到调用的链路信息了,如下图所示:
也可以点击进去,进一步查看,通过其他维度检查这个调用链路的详细信息,比如中间经历了哪些步骤,各个链路的耗费时间
也可以切换到依赖视图,以拓扑图的形式展示服务的调用链路情况
七、写在文末
本文详细介绍了sleuth和zipkin的使用,在springcloud的微服务生态中,这两个组件的搭配可以快速实现服务链路的追踪,接入简单,对服务的可观测性来说是一个很好的补充,而zipkin的思想,也影响甚至促成了应用可观测领域很多解决方案的诞生,有必要深入学习和掌握其适用场景,本篇到此结束感谢观看。