《吃透微服务》- 服务追踪之Sleuth

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 本文主要介绍 SpringCloud中动态链路追踪

关于微服务的概念我们在之前的两篇文章中都已经做出了相应的见解,没看过的小伙伴可以空降查看一番,不同见解欢迎后台留言!




这么这篇我们继续我们的主题 《吃透微服务》 ,继续了解分布式系统中解决链路追踪的方案 --- Sleuth吃透 当然可以作为一个噱头,但也可以作为一个目标!


微服务的好坏我们不再争议,最近看到很多反面宣传微服务的特性,不知道是否大数据精准投喂~ ps:估计后台人物画像已经标签为一个反微分子了。这当然是一句玩笑话,结束玩笑,我们来为微服务的学习添砖加瓦!


微服务的关键在于拆分服务,但是关键不在 ,而在于合适的大小。当我们跨出拆分服务的那一刻起,我们就得对我们拆分后的服务负责,这个是一个程序员应有的担当!当服务出现问题的时候,你是否还苦于排查,而无从定位。线上的代码我们无法 debug,找出问题的时刻往往出现以下对话:


网络异常,图片无法展示
|


除了无奈的苦笑,只能盲目的摸索,终于有一天程序员小菜不再妥协,力求解决该问题。咱们能不能搞个类似监控的功能,当请求进来的时候,分配一个身份令牌的给它,当它在微服务中游走的时候,每个服务都会留下它的痕迹,当它出现问题的时候,我们只需要检查游走到哪一个微服务,相当于画一个行为轨迹,通过行为轨迹追踪服务的调用问题!沾沾自喜的同时犯嘀咕了,这说起来容易,实现起来好像有点困难~退堂鼓即将敲响,便想到微服务中怎么可能没有人想到该问题,于是便游走于微服务组件之中,力求找到解决问题的实现。终于,Sleuth 出现了。


Sleuth


一、认识 Sleuth


前面做了那么多的铺垫,就是想引出 Sleuth 这玩意。洋洋洒洒说了一堆,那就简单用一句话描述一下它的作用:在分布式系统中提供追踪解决方案。它大量借用了 Google Dapper  的设计,难道又是个换壳的玩意?


我们先来了解一下 Sleuth 中的术语和相关概念,只为了让我们更加专业,更好 吹着牛x谈架构


  • Trace


由一组 Trace Id 相同的 Span 串联形成一个树状结构。为了实现请求追踪,当请求到达分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的标识(即 Trace Id),同时在恩不是系统内部流转的时候,框架是中保持传递该唯一值,直到整个请求的返回。那么我们就可以使用该唯一标识将所有的请求串联起来,形成一条完整的请求链路。


  • Span


代表了一组基本的工作单元。为了统计各处理单元的延迟,当请求到达各个服务组件的时候,也通过一个唯一标识(SpanId)来标记它的开始,具体过程和结束。通过 SpanId 的开始和结束时间戳,就能统计该 Span 的调用时间,除此之外,我们还可以获取如事件的名称,请求信息等元数据


  • Annotation


用于记录一段时间内的事件。内部使用的重要注释如下:


  1. cs(Client Send):客户端发出请求,开始一个请求的事件


  1. sr(Server Received) :服务端接受到请求开始进行处理。sr - cs = 网络延迟(服务调用的时间)


  1. ss(Server Send):服务端处理完毕准备发送到客户端。ss -sr = 服务器上的请求处理时间


  1. cr(Client Reveived):客户端接受到服务端的响应,请求结束。cr - sr = 请求的总时间


网络异常,图片无法展示
|


理解完三个概念,我们下面就直接上手认识!


二、掌握 Sleuth


我们老样子请出我们的微服务项目:


网络异常,图片无法展示
|


简简单单几个服务做个自我介绍


  • store-gateway: 服务网关


  • store-order: 订单服务


  • store-product: 产品服务


然后我们需要在父工程中引入 Sleuth 依赖


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>


直接在父工程的 dependencies 中引入,这样子每个子服务就可以不同重复引入该依赖


然后开始我们的简易代码模式:


store-order服务


OrderController:


网络异常,图片无法展示
|


ProductService:


网络异常,图片无法展示
|


store-product 服务


ProductController:


网络异常,图片无法展示
|


我们在订单服务 中使用 Feign 远程调用 产品服务 中的接口,然后启动服务调用后看控制台打印:


网络异常,图片无法展示
|


注意看我圈出来的部分,有没有发现了些许不同,没错!这一串字符中包含的信息有 服务名 / TraceId / SpanId。依次调用有一个全局的 TraceId,将调用链路穿起来。通过分析微服务的日志,不难看出请求的具体过程。但是有个弊端,但服务数量增多,或者日志数量增多,从日志文件中捞出某个请求的调用过程,可并非是件易事,那么有没有一个可以全文检索和可视化展示的插件帮助我们解决该问题?既然提出问题,小菜自然已经找到解决问题的方法!那就是 ZipKin


三、使用 ZipKin


ZipKinTwitter 开源的一个项目,它也是基于 Google Dapper 实现的,主要作用便是解决我们上面提到的问题:收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集,存储,查找和展现


我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源!


我们除了面向开发的 API 接口之外, ZipKin 也提供了方便的 UI 组件来帮我们更加直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。


听到 UI 组件是不是感到眼前一亮,说明我们可以通过控制台更好的管理链路跟踪


不仅如此,ZipKin 还提供了可插拔式的数据存储方式,例如:In-Memory、MySQL、Cassandra以及Elasticsearch。支持方式不算少,总有一种你喜欢的!


我们来看看 ZipKin 的基础架构图:


网络异常,图片无法展示
|


可以看出 ZipKin 结构并不复杂,有四个核心组件构成:


  • Collector:收集器组件。主要用于处理外部系统发现过来的跟踪信息,然后将这些信息转换为 ZipKin 内部处理的 Span 格式,以便支持后续的存储、分析、展示等功能


  • Storage: 存储组件。主要用于对处理收集器接收到的跟踪信息,默认会将这些信息存储到内存中,我们可以修改存储策略,将其存储到我们的其他存储仓库中


  • RestFul API:API 组件。用于提供外部访问的接口,比如客户端的跟踪信息,或外接系统的访问信息


  • WebUI:UI 组件。基于 API 组件实现的上层应用,通过 UI 组件用户可以方便而直观地查询和分析跟踪信息


因此 ZiPKin 使用起来有些类似我们上篇说到的 Sentinel ,它分为 服务端客户端

客户端就是指微服务中的应用,在客户端中配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务中的 Sleuth 的监听器监听,并生相应的 TraceSpan 信息发送给服务端。


1. ZipKin 服务端


服务端是一个现成的 SpringBoot 服务,我们只需要下载 jar 包 ,便可以直接运行!下载地址


然后我们通过命令行的方式启动即可:


java -jar zipkin-server-2.12.9-exec.jar


成功启动后通过访问 http://localhost:9411 可以看到以下页面:


网络异常,图片无法展示
|


到这步为止,我们服务端就已经成功安装。然后回到我们的客户端集成上去


2. ZipKin 客户端


我们需要在每个服务中引入 ZipKin 的依赖


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>


然后在配置文件中进行配置:


spring:
  zipkin:
    base-url: http://127.0.0.1:9411/  #zipkin 服务端地址
    discoveryClientEnabled: false     #让nacos把它当成一个URL,而不要当做服务名
  sleuth:
    sampler:
      probability: 1.0 #采样的百分比


然后我们回到项目中,启动项目通过访问我们上面已经定义好的接口访问微服务,之后在 ZipKin 的UI界面进行观察


网络异常,图片无法展示
|


可以看到已经出现了我们刚刚访问微服务的请求链路了,点击其中一条记录可以查看具

体的访问路线。


网络异常,图片无法展示
|


通过对请求链路进行追踪,就可以确定服务的哪一个模块更耗时,进而可以进行优化或者排查 Bug


3. ZipKin 持久化


在 ZipKin 中默认会将链路跟踪的数据保存到内存中,但是这种方式明显不适合于生产环境。因此在 ZipKin 中支持将追踪链路的数据持久化到 mysql 数据库中或 elasticsearch 中。


MySQL


  • 首先我们需要配置数据库信息


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,
    `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'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';
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(`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';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
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
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);


网络异常,图片无法展示
|


  • 启动时指定 mysql 信息


java -DSTORAGE_TYPE=mysql -DMYSQL_HOST=127.0.0.1 -DMYSQL_TCP_PORT=3306 -DMYSQL_DB=zipkin -DMYSQL_USER=root -DMYSQL_PASS=root -jar zipkin-server-2.12.9-exec.jar 


ElasticSearch


  • 启动 ES


  • 启动时指定 ES 信息


java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=elasticsearch --ES-HOST=localhost:9200


END


到这里我们就完成了分布式系统中服务链路跟踪的解决!那为我们解决了问题呢?


  • 跨微服务的API调用发生异常,快速定位出问题出在哪里。


  • 跨微服务的API调用发生性能瓶颈,迅速定位出性能瓶颈。


相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
1月前
|
Cloud Native Java API
聊聊从单体到微服务架构服务演化过程
本文介绍了从单体应用到微服务再到云原生架构的演进过程。单体应用虽易于搭建和部署,但难以局部更新;面向服务架构(SOA)通过模块化和服务总线提升了组件复用性和分布式部署能力;微服务则进一步实现了服务的独立开发与部署,提高了灵活性;云原生架构则利用容器化、微服务和自动化工具,实现了应用在动态环境中的弹性扩展与高效管理。这一演进体现了软件架构向着更灵活、更高效的方向发展。
|
29天前
|
Kubernetes 负载均衡 Docker
构建高效后端服务:微服务架构的探索与实践
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于任何在线业务的成功至关重要。本文将深入探讨微服务架构的概念、优势以及如何在实际项目中有效实施。我们将从微服务的基本理念出发,逐步解析其在提高系统可维护性、扩展性和敏捷性方面的作用。通过实际案例分析,揭示微服务架构在不同场景下的应用策略和最佳实践。无论你是后端开发新手还是经验丰富的工程师,本文都将为你提供宝贵的见解和实用的指导。
|
28天前
|
监控 API 持续交付
构建高效后端服务:微服务架构的深度探索
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于支撑复杂的业务逻辑和海量数据处理至关重要。本文深入探讨了微服务架构的核心理念、实施策略以及面临的挑战,旨在为开发者提供一套构建高效、可扩展后端服务的方法论。通过案例分析,揭示微服务如何帮助企业应对快速变化的业务需求,同时保持系统的稳定性和灵活性。
46 9
|
30天前
|
监控 安全 Java
构建高效后端服务:微服务架构深度解析与最佳实践###
【10月更文挑战第19天】 在数字化转型加速的今天,企业对后端服务的响应速度、可扩展性和灵活性提出了更高要求。本文探讨了微服务架构作为解决方案,通过分析传统单体架构面临的挑战,深入剖析微服务的核心优势、关键组件及设计原则。我们将从实际案例入手,揭示成功实施微服务的策略与常见陷阱,为开发者和企业提供可操作的指导建议。本文目的是帮助读者理解如何利用微服务架构提升后端服务的整体效能,实现业务快速迭代与创新。 ###
63 2
|
1月前
|
消息中间件 Kafka 数据库
微服务架构中,如何确保服务之间的数据一致性?
微服务架构中,如何确保服务之间的数据一致性?
|
1月前
|
监控 Java 对象存储
监控与追踪:如何利用Spring Cloud Sleuth和Netflix OSS工具进行微服务调试
监控与追踪:如何利用Spring Cloud Sleuth和Netflix OSS工具进行微服务调试
44 1
|
1月前
|
运维 Kubernetes 开发者
构建高效后端服务:微服务架构与容器化技术的结合
【10月更文挑战第18天】 在数字化转型的浪潮中,企业对后端服务的要求日益提高,追求更高的效率、更强的可伸缩性和更易于维护的系统。本文将探讨微服务架构与容器化技术如何结合,以构建一个既灵活又高效的后端服务体系。通过分析当前后端服务面临的挑战,介绍微服务和容器化的基本概念,以及它们如何相互配合来优化后端服务的性能和管理。本文旨在为开发者提供一种实现后端服务现代化的方法,从而帮助企业在竞争激烈的市场中脱颖而出。
26 0
|
2月前
|
消息中间件 Kafka 数据库
微服务架构中,如何确保服务之间的数据一致性
微服务架构中,如何确保服务之间的数据一致性
|
2月前
|
Java API 对象存储
微服务魔法启动!Spring Cloud与Netflix OSS联手,零基础也能创造服务奇迹!
这段内容介绍了如何使用Spring Cloud和Netflix OSS构建微服务架构。首先,基于Spring Boot创建项目并添加Spring Cloud依赖项。接着配置Eureka服务器实现服务发现,然后创建REST控制器作为API入口。为提高服务稳定性,利用Hystrix实现断路器模式。最后,在启动类中启用Eureka客户端功能。此外,还可集成其他Netflix OSS组件以增强系统功能。通过这些步骤,开发者可以更高效地构建稳定且可扩展的微服务系统。
59 1
|
2月前
|
测试技术 微服务
微服务(八)-服务网关zuul(四)
微服务(八)-服务网关zuul(四)
下一篇
无影云桌面