分布式链路追踪入门篇-基础原理与快速应用
为什么需要链路追踪?
我们程序员在日常工作中,最常做事情之一就是修bug了。如果程序只是运行在单机上,我们最常用的方式就是在程序上打日志,然后程序运行的过程中将日志输出到文件上,然后我们根据日志去推断程序是哪一步发生了问题。但是如果我们的程序是部署在分布式架构的各个服务上,我们再用这种方法去查看一个又一个日志文件,这就显得非常的低效了。所以这时候如果有一个可以帮助我们根据时间脉络将所有的信息都汇集起来并以可视化的方式直观展示给我们看,我们的bugfix是不是就变得事半功倍了呢?
一、什么是链路追踪?
链路追踪(Distributed Tracing)是一种用于监测和诊断分布式应用程序中请求路径的技术。在分布式系统中,单个请求可能会涉及多个服务和组件。链路追踪通过记录和分析请求在这些服务之间的传递路径和执行情况,帮助开发人员和运维团队理解系统的运行状况、性能和问题。
二、链路追踪是怎么实现的?
1.链路追踪关键概念介绍
- Span(片段): 在链路追踪中,Span 是描述单个操作或事件的基本单元。一个请求被分解成一个或多个 Span,每个 Span 表示一个操作的开始和结束。例如,一个数据库查询、一个 HTTP 请求、一个函数调用等都可以作为一个 Span。
- Context(上下文): 在链路追踪中,上下文是指跨越不同服务的信息传递。每个 Span 都关联一个上下文,允许跟踪系统将相关的 Span 连接起来,以显示请求的完整路径。
- Trace ID(追踪标识): Trace ID 是整个请求路径的唯一标识符。它用于将整个请求的所有 Span 关联到同一个 Trace 中。当一个请求进入系统时,生成一个唯一的 Trace ID,并在整个请求过程中一直保持不变,以确保所有的 Span 都能够关联到同一个 Trace 中。
- Span ID(Span 标识): Span ID 是用于标识单个操作或事件的唯一标识符。每个 Span 都有自己的 Span ID,它用于在 Trace 中标识不同的操作或事件。
2.span是怎么基于context进行关联的?
由上面的概念我们大概可以想象到,一条追踪链路其实是由多个span组成的,而span之间是基于每一个span的context进行关联 (即根据context里的同一个trace id进行关联)
三、OpenTelemetry、Jaeger这些和链路追踪有什么关系?
- OpenTelemetry 是一个用于跟踪和监控分布式系统的开放式标准和工具集。它提供了一套标准的API 和工具,用于生成、导出和聚合跟踪数据,并将这些数据发送到各种后端,如 Jaeger、Zipkin、Prometheus 等。
- Jaeger这些系统为链路追踪提供了一种可视化和分析分布式系统的能力,通过记录请求的执行路径和操作(span),在一个直观的用户界面中展示整个系统中的请求传播路径和性能数据。
四、怎么快速使用OpenTelemetry、Jaeger实现一个链路追踪的demo
- 步骤1:需要安装Jaeger,并运行Jaeger。Jaeger官方入门文档
为了快速演示,我们可以使用官方推荐的测试方式用docker快速启动:
然后,打开http://localhost:16686就可以访问 Jaeger UI了。docker run --rm --name jaeger \-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \-p 6831:6831/udp \-p 6832:6832/udp \-p 5778:5778 \-p 16686:16686 \-p 4317:4317 \-p 4318:4318 \-p 14250:14250 \-p 14268:14268 \-p 14269:14269 \-p 9411:9411 \jaegertracing/all-in-one:1.51
- 步骤2:运行下面代码,具体代码请拉取我github上的demo
package mainimport ("context""fmt""log""net/http""go.opentelemetry.io/otel"`go.opentelemetry.io/otel/attribute`"go.opentelemetry.io/otel/exporters/trace/jaeger"`go.opentelemetry.io/otel/sdk/resource`sdktrace "go.opentelemetry.io/otel/sdk/trace"`go.opentelemetry.io/otel/semconv`svc `otel/demo1/svc`
)// 初始化 OpenTelemetry
func initTracer() *sdktrace.TracerProvider {exporter, err := jaeger.NewRawExporter(jaeger.WithAgentEndpoint(func(options *jaeger.AgentEndpointOptions) {options.Host = "localhost"options.Port = "6831"}),)if err != nil {log.Fatalf("Error creating Jaeger exporter: %v", err)}tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter),sdktrace.WithSampler(sdktrace.AlwaysSample()),sdktrace.WithResource(resource.NewWithAttributes(semconv.ServiceNameKey.String("demo_service"), // 服务名)),)otel.SetTracerProvider(tp)return tp
}func main() {tp := initTracer()defer func() {if cerr := tp.Shutdown(context.Background()); cerr != nil {log.Fatalf("Error shutting down tracer provider: %v", cerr)}}()//启动http服务器http.HandleFunc("/demo", handleRequest)go func() {if err := http.ListenAndServe(":8080", nil); err != nil {log.Fatalf("Error starting Service A server: %v", err)}}()//模拟请求SimulateRequest()
}func handleRequest(w http.ResponseWriter, req *http.Request) {tracer := otel.Tracer("root")//开始创建root spanctx, span := tracer.Start(req.Context(), "span root")defer span.End()//可以在span上记录一些信息,例如日志、请求参数、sql语句等span.SetAttributes(attribute.String("some root service info", "This is the root service"),)//访问服务Asvc.CallServiceA(ctx)//访问服务Bsvc.CallServiceB(ctx)w.WriteHeader(http.StatusOK)fmt.Fprintf(w, "Response from Service Root")
}func SimulateRequest() {req, err := http.NewRequest("GET", "http://localhost:8080/demo", nil)if err != nil {log.Fatalf("Creating request fail: %v", err)}resp, err := http.DefaultClient.Do(req)if err != nil {log.Fatalf("Request failed: %v", err)}defer resp.Body.Close()fmt.Println("Response received from Root Service")
}
运行后打开http://localhost:16686,选择对应的service查找trace可以看到
五、总结
- 链路追踪是依靠于一个随机生成的trace_id,一条链路对应唯一一个trace_id。
- Span 是描述单个操作或事件的基本单元。一个请求被分解成一个或多个 Span。即一条链路是由多个span组成的。
- 在链路追踪中,context(上下文)是指跨越不同服务的信息传递。每个 Span 都关联一个上下文。
- OpenTelemetry 是一个用于跟踪和监控分布式系统的开放式标准和工具集。提供了一套标准的API 和工具,用于生成、导出和聚合跟踪数据,并将这些数据发送到各种后端。
- Jaeger、Zipkin、Prometheus等这些可以接收OpenTelemetry发送过来的数据,可以提供可视化的展示和分析数据的能力。
相关文章:

分布式链路追踪入门篇-基础原理与快速应用
为什么需要链路追踪? 我们程序员在日常工作中,最常做事情之一就是修bug了。如果程序只是运行在单机上,我们最常用的方式就是在程序上打日志,然后程序运行的过程中将日志输出到文件上,然后我们根据日志去推断程序是哪一…...

新的centos7.9安装jenkins—(一)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 因为是用java8,所以还是要最后java8版本的jenkins,版本号是2.346.3,后…...
Go语言初始化已有环境,跟踪已有依赖环境
在Go语言中,go.mod文件是Go模块的管理文件,用于跟踪和管理项目的依赖关系。go.sum 文件是 Go 语言模块的另一个关键文件,它记录了项目依赖的确切版本以及相应的哈希值。如果你得到了一个包含go.mod和go.sum文件的Go代码,ÿ…...

短视频获客系统成功分享,与其开发流程与涉及到的技术
先来看实操成果,↑↑需要的同学可看我名字↖↖↖↖↖,或评论888无偿分享 一、短视频获客系统的开发流程 1. 需求分析:首先需要对目标用户进行深入了解,明确系统的功能和目标,制定详细的需求文档。 2. 系统设计&#…...

antv/g6的学习总结
新建一个简单实例 1、使用命令行在项目目录下执行以下命令 cnpm install --save antv/g6 2、创建容器 <div id"mountNode"></div> 3、在需要用的 G6 的 JS 文件中导入 import G6 from antv/g6; 4、 数据准备 引入 G6 的数据源为 JSON 格式的对象。…...

带你用uniapp从零开发一个仿小米商场_6. 配置uniapp项目底部导航栏tabbar
uniapp底部tabbar介绍 在uni-app中,底部tabbar是一种常见的导航方式,它可以让用户在应用的不同页面之间进行切换。通过tabBar配置项,开发者可以指定一级导航栏和tab切换时显示的对应页。 在底部tabbar中,每个tab都有一个页面路径…...

curl添加https服务
CURL支持的通信协议有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。 首选删除系统自带的openssl,因为他只有可执行程序和库,没有头文件。 sudo apt-get remove openssl openssl官网&am…...

【Flink】Standalone运行模式
独立模式是独立运行的,不依赖任何外部的资源管理平台;当然独立也是有代价的:如果资源不足,或者出现故障,没有自动扩展或重分配资源的保证,必须手动处理。所以独立模式一般只用在开发测试或作业非常少的场景…...

Kotlin学习——流程控制,when,循环,range工具 kt里的equals if实现类似三元表达式的效果
Kotlin 是一门现代但已成熟的编程语言,旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作,并提供了多种方式在多个平台间复用代码,以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…...

利用STM32CubeMX解读时钟树
1,低速时钟 LSE是外部晶振作时钟源,主要提供给实时时钟模块,所以一般采用32.768KHz。LSI是由内部RC振荡器产生,也主要提供给实时时钟模块,频率大约为40KHz。(LSE和LSI)只是提供给芯片中的RTC(实时时钟)及IWDG(独立看门…...

Unity-链接MySql8.0
链接MySql8.0 1.准备dll 一、找到l18N相关的dll 这里给出一个参考地址 D:\Unity\2020.3.48f1c1\Editor\Data\MonoBleedingEdge\lib\mono\unityjit在里面找到如下图的四个dll 二、下载数据库链接dll https://downloads.mysql.com/archives/c-net/在这里搜索历史版本(Archiv…...
Hive csv文件导入Hive
一、如何把csv文件导入Hive (1) 在Hive中建立与csv相对应的表 create table if not exists tmp.tmp_wenxin_20231123 (redeem_code_id string comment ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE;创建了一张名为tmp_wenxin_20231123的hive表&am…...

嵌入式的学习需要合理规划时间
低级的欲望放纵即可获得,高级的欲望只有克制才能达成。——卡耐基1、粉丝的误会 很多粉丝,问我, "胡老师我想报您的培训班。" ... 得知我知识业余时间写文章,紧接着又会问, "jg单位这么清闲啊&#…...

HTTP协议发展
HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC) 每一代HTTP解决了什么问题? 下图说明了主要功能。 HTTP 1.0 于 1996 年最终确定并完整记录。对同一服务器的每个请求都需要单独的 TCP 连接。 HTTP 1.1 于 1997 年发布。TCP 连接可以保持打开状态…...

杰发科技AC7801——ADC软件触发的简单使用
前言 7801资料读起来不是很好理解,大概率是之前MTK的大佬写的。在此以简单的方式进行描述。我们做一个简单的规则组软件触发Demo。因为规则组通道只有一个数据寄存器,因此还需要用上DMA方式搬运数据到内存。 AC7801的ADC简介 7801的ADC是一种 12 位 逐…...

佳易王个体诊所门诊电子处方软件试用版下载,佳易王电子处方软件的配方模板功能作用与教程
佳易王个体诊所门诊电子处方软件试用版下载,佳易王电子处方软件的配方模板功能作用与教程 1、软件试用版及教程可以点击下方的官网卡片 2、软件中有一个实用的功能,配方模板功能,在开处方单时候可以一键导入配方,节省时间。 而…...

FFmpeg零基础学习(二)——视频文件信息获取
目录 前言正文一、获取宽高信息1、核心代码2、AVFormatContext3、avformat_alloc_context4、avformat_open_input5、avformat_find_stream_info6、av_dump_format7、av_find_best_stream End、遇到的问题1、Qt Debug模式avformat_alloc_context 无法分配对象,而Rele…...

探索 Vue 中的 bus.$emit:实现组件通信的强大工具
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...

2017年五一杯数学建模A题公交车排班问题解题全过程文档及程序
2017年五一杯数学建模 A题 公交车排班问题 原题再现 随着徐州市经济的快速发展,公交车系统对于人们的出行扮演着越来越重要的角色。在公交车资源有限的情况下,合理的编排公交车的行车计划成为公交公司亟待解决的问题。以下给出公交车排班问题中的部分名…...

【c++】——类和对象(下) ——内存管理
作者:chlorine 专栏:c专栏 目录 💻 C/C内存分布 💻C语言中动态内存管理方式:malloc/calloc/realloc/free 编辑 💻C内存管理方式 👉new/delete操作内置类型 👉new和delete操作自定义类型 …...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...