【分布式】分布式链路跟踪技术

为什么需要分布式链路追踪

提到分布式链路追踪,我们要先提到微服务。相信很多人都接触过微服务。微服务是一种开发软件的架构和组织方法,它侧重将服务解耦,服务之间通过API通信。使应用程序更易于扩展和更快地开发,从而加速新功能上线。
在这里插入图片描述

加速研发快速迭代,让微服务在业务驱动的互联网领域全面普及,独领风骚。但是,随之而来也产生了新问题:当生产系统面对高并发,或者解耦成大量微服务时,以前很容易就能实现的监控、预警、定位故障就变困难了。

接下来我们拿一笔支付的例子来举例
在这里插入图片描述
比如支付付款这样一个行为,其实是对多个服务器发起了一个请求,这个请求会被发送到多个微服务系统,通俗的讲,这些微服务系统分别用来查询用户信息,查询余额,请求支付等等。每个子系统的做完这一套操作后,会把对应结果展示给用户。

用户一次操作,做了这么一个“全局操作”。任何一个子系统变慢,都会导致最终的操作变得慢,那用户体验就会很差了。

看到这里,你可能会想,体验差我们做优化不就好了么?确实如此,但一般情况,一个前端或者后端工程师虽然知道系统查询耗时,但是他无从知晓这个问题到底是由哪个服务调用造成的,或者为什么这个调用性能差强人意。

这个工程师可能无法准确定位到这次全局搜索是调用了哪些服务,因为新的服务、乃至服务上的某个功能,都有可能在任何时间上过线或修改过。其次,你不能苛求这个工程师对所有参与这次全局搜索的服务都了如指掌,每一个服务都有可能是由不同的团队开发或维护的。再次,搜索服务还同时还被其他客户端使用,比如手机端,这次全局搜索的性能问题甚至有可能是由其他应用造成的。

什么是分布式链路追踪

对于上面的情况,我们迫切需要一些新工具,帮我们精准分析性能问题。于是,分布式系统下链路追踪技术(Distributed Tracing)出现了。

它的核心思想是:在用户一次请求服务的调⽤过程中,无论请求被分发到多少个子系统中,子系统又调用了更多的子系统,我们把系统信息和系统间调用关系都追踪记录下来。最终把数据集中起来可视化展示。它会形成一个有向图的链路,看起来像下面这样
在这里插入图片描述

链路Trace的核心结构

应用的稳定性,以及出现问题的时候,怎样的快速定位到真正的原因。主要体现在怎样监控系统,怎样从日志上快速的找到错误,怎样快速的知道调用链是不是出现了问题,以及应用的运行时有没有出问题,应用依赖的数据库,中间件等是不是出现问题了。这也是大家经常听到的观测性的大三要素,监控,日志,链路。

我们如何将这个链路串联起来呢?

有两种方式:span(链式记录依赖)和RPCID(层级计数器)。我们在记录日志带上UUID的同时,也带上RPCID这个信息,帮我们把日志关联关系串联起来。

我们先看看span实现:
在这里插入图片描述

结合上图,我们分析一下span的链式依赖记录方式。对于代码来说,写的很多功能会被封装成功能模块(Service、Model),我们通过组合不同的模块实现业务功能,并且记录这两个模块、两个服务间或是资源的调用依赖关系。

span这个设计会通过记录自己上游依赖服务的SpanID实现上下游关系关联(放在Parent ID中),通过整理span之间的依赖关系就能组合成一个调用链路树。

那RPCID方式是什么样的呢?RPCID也叫层级计数器,为了方便理解,我们来看下面这张图:
在这里插入图片描述

RPCID的层级计数器实现很简单,第一个接口生成RPCID为 1.1 ,RPCID的 前缀 是1, 计数器 是1(日志记录为 1.1)。

当所在接口请求其他接口或数据服务(MySQL、Redis、API、Kafka)时, 计数器 +1,并在请求当中带上1.2这个数值(因为当前的 前缀 + “.” + 计数器值 = 1.2),等到返回结果后,继续请求下一个资源时继续+1,期间产生的任何日志都会记录当前 前缀 +“.”+ 计数器值。

每一层收到了前缀后,都在后面加了一个累加的计数器,实际效果如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c71ece9a65144baea55a08facefd12c1.png在这里插入图片描述
而被请求的接口收到请求时,如果请求传递了TraceID,那么被请求的服务会继续使用传递过来的TraceID,如果请求没有TraceID则自己生成一个。同样地,如果传递了RPCID,那么被请求的服务会将传递来的RPCID当作前缀,计数器从1开始计数。

相对于span,通过这个层级计数器做出来的RPCID有两个优点。

1、第一个优点是我们可以记录请求方日志,如果被请求方没有记录日志,那么还可以通过请求方日志观测分析被调用方性能(MySQL、Redis)。

3、另一个优点是哪怕日志收集得不全,丢失了一些,我们还可以通过前缀有几个分隔符,判断出日志所在层级进行渲染。举个例子,假设我们不知道上图的1.5.1是谁调用的,但是根据它的UUID和层级1.5.1这些信息,渲染的时候,我们仍旧可以渲染它大概的链路位置。

我们前面提到,请求和被请求方通过传递TraceID和RPCID(或SpanID)来实现链路的跟踪,下面列举几个常见的方式:
1、HTTP协议放在Header;
2、RPC协议放在meta中传递;
3、队列可以放在消息体的Header中,或直接在消息体中传递;
4、其他特殊情况下可以通过网址请求参数传递

那么应用内多线程和多协程之间如何传递TraceID呢?一般来说,我们会通过复制一份Context传递进入线程或协程,并且如果它们之前是并行关系,我们复制之后需要对下发之前的RPCID计数器加1,并把前缀和计数器合并成新的前缀,以此区分并行的链路。

日志样式的定义

日志建议使用JSON格式,所有字段除了标注为string的都建议保存为字符串类型,每个字段必须是固定数据类型,选填内容如果没有内容就直接不输出。

这样设计其实是为了适配Elasticsearch+Kibana,Kibana提供了日志的聚合、检索、条件检索和数值聚合,但是对字段格式很敏感,不是数值类型就无法聚合对比。

日志实现方式

“侵入式埋点SDK”VS“AOP方式埋点”?
那么如果底层代码不能更新,如何简单暴力地实现链路跟踪呢?

这时候我们可以改造分级日志,让它每次在落地的时候都把TraceId和RPCID(或SpanID)带上,就会有很好的效果。如果数据底层做了良好的封装,我们可以在发起请求部分中写一些符合标准性能的日志,在框架的统一异常处理中也注入我们的标准跟踪,即可实现关键点的监控。

当然如果条件允许,我们最好提供一个标准的SDK,让业务研发伙伴按需调用,这能帮助我们统一日志结构。毕竟手写很容易格式错乱,需要人工梳理,不过即使混乱,也仍旧有规律可言,这是ELK架构的强大之处,它的全文检索功能其实不在乎你的输入格式,但是数据统计类却需要我们确保各个字段用途固定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/330092.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python从入门到进阶】46、58同城Scrapy项目案例介绍

接上篇《45、Scrapy框架核心组件介绍》 上一篇我们学习了Scrapy框架的核心组件的使用。本篇我们进入实战第一篇,以58同城的Scrapy项目案例,结合实际再次巩固一下项目结构以及代码逻辑的用法。 一、案例网站介绍 58同城是一个生活服务类平台&#xff0c…

qt-C++笔记之QProcess

qt-C笔记之QProcess code review! 文章目录 qt-C笔记之QProcess一.示例:QProcess来执行系统命令ls -l命令并打印出结果说明 二.示例:QProcess来执行系统命令ls -l命令并打印出结果,代码进一步丰富三.示例:使用 QProcess 在 Qt 中…

el-date-picker日期时间选择器限制可选的日期范围

业务场景&#xff1a;需要限制日期时间选择器可选择的日期&#xff0c;有两种模式&#xff0c; 一种是已知范围&#xff0c;只能选已知范围内的日期&#xff0c; 另一种是知道最近天数&#xff0c;只能选今天往前的天数内的日期&#xff0c;超出不能选。 <el-date-picker v-…

高性能、可扩展、分布式对象存储系统MinIO的介绍、部署步骤以及代码示例

详细介绍 MinIO 是一款流行的开源对象存储系统&#xff0c;设计上兼容 Amazon S3 API&#xff0c;主要用于私有云和边缘计算场景。它提供了高性能、高可用性以及易于管理的对象存储服务。以下是 MinIO 的详细介绍及优缺点&#xff1a; 架构与特性&#xff1a; 开源与跨平台&am…

加密流量:成功 NDR 策略的关键因素

IT 决策者之间一直在就基于网络的可视性日益增长的需求进行对话。然而&#xff0c;由于超过 95% 的基于互联网的流量都被加密&#xff0c;因此需要实时解密作为成功的网络检测和响应(NDR) 策略的要求&#xff0c;这在某种程度上是一个棘手的问题。 此外&#xff0c;决策者还面…

【C++核心编程(四)】

一、继承 继承是面向对象三大特性之一。 有些类与类之间存在特殊的关系&#xff0c;例如下图中: 我们发现&#xff0c;定义这些类时&#xff0c;下级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性。 这个时候我们就可以考虑利用继承的技术&#xff0c;减少重复代…

python统计分析——箱线图(plt.boxplot)

参考资料&#xff1a;用python动手学统计学 使用matplotlib.pyplot.boxplot()函数绘制箱线图 import numpy as np import pandas as pd from matplotlib import pyplot as pltdata_set1np.array([2,3,3,4,4,4,4,5,5,6]) data_set2np.array([[2,3,3,4,4,4,4,5,5,6],[5,6,6,7,7…

十八:爬虫-JS逆向(下)

一&#xff1a;AES与DES DES对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥&#xff0c;信息的发送者。和信息的接收者在进行信息的传输与处理时&#xff0c;必须共同持有该密钥(称为对称密码),是一种对称加密算法。一般来说加密用的是encrypt()函…

[redis] redis的安装,配置与简单操作

一、缓存的相关知识 1.1 缓存的概念 缓存是为了调节速度不一致的两个或多个不同的物质的速度&#xff0c;在中间对速度较慢的一方起到加速作用&#xff0c;比如CPU的一级、二级缓存是保存了CPU最近经常访问的数据&#xff0c;内存是保存CPU经常访问硬盘的数据&#xff0c;而且…

给您的应用添加弹窗

概述 在我们日常使用应用的时候&#xff0c;可能会进行一些敏感的操作&#xff0c;比如删除联系人&#xff0c;这时候我们给应用添加弹窗来提示用户是否需要执行该操作&#xff0c;如下图所示&#xff1a; 弹窗是一种模态窗口&#xff0c;通常用来展示用户当前需要的或用户必须…

OpenVINS学习6——VioManagerHelper.cpp,VioManagerOptions.h学习与注释

前言 VioManager类里还有VioManagerHelper.cpp,VioManagerOptions.h这两个文件&#xff0c;也包含了一些函数&#xff0c;这次接着看这个 。 整体分析 void VioManager::initialize_with_gt(Eigen::Matrix<double, 17, 1> imustate) 给一个状态&#xff0c;然后初始化…

学生信息管理系统(录入、查找、删除、修改、排序、统计等功能实现)超详细完整代码,建议保存。

许多老师都会布置Python期末大作业&#xff0c;作业题目很多就是学生信息管理系统&#xff0c;以前都是练习小题目&#xff0c;几十行代码就能搞定&#xff0c;而完整的写完这个系统我用了差不多400行代码。完整写完这个系统&#xff0c;是对一个学期所学知识的进一步深入了解于…