基于OpenTelemetry实现分布式链路追踪

基于OpenTelemetry实现分布式链路追踪

文章目录

在微服务架构普及的当下,一个用户请求往往会经过多个服务节点的协同处理,一旦出现接口超时、报错等问题,仅凭日志定位根因变得异常困难。分布式链路追踪作为可观测性三大核心能力(日志、指标、追踪)之一,能清晰还原请求的全链路路径、各环节耗时及异常信息,是保障分布式系统稳定运行的关键工具。本文将详细介绍如何基于 OpenTelemetry(简称 OTel)结合 Jaeger,快速搭建一套轻量、易用的分布式链路追踪系统,并完成 Java 服务的链路接入。

本方案在为链路追踪入门实践。

一、方案整体介绍

核心组件说明

OpenTelemetry:统一的可观测性采集框架

OpenTelemetry 是 CNCF 孵化的开源可观测性框架,核心目标是统一分布式追踪、指标、日志的采集标准,解决不同厂商 / 工具采集格式不兼容的问题。其核心组件包括:

  • SDK/Agent:多语言埋点能力,支持自动埋点(如 Java Agent 无需修改业务代码)和手动埋点,负责生成追踪数据(Trace/Span);
  • Collector:数据处理中间件,提供数据接收、过滤、转换、转发能力,解耦采集端和存储端,支持对接多种后端(Jaeger、Prometheus、Elasticsearch 等);
  • Exporter:数据导出组件,将采集的可观测数据发送到指定后端。

OpenTelemetry 的优势在于无厂商锁定、生态丰富,能适配绝大多数微服务技术栈,是当前分布式追踪采集层的主流选择。

Jaeger:轻量的追踪数据存储与可视化工具

Jaeger 是 Uber 开源的分布式追踪系统,专注于追踪数据的存储、查询和可视化,提供开箱即用的 All-in-One 部署模式,适合中小规模场景快速落地。其核心能力包括:

  • 接收 OpenTelemetry、Zipkin 等标准格式的追踪数据;
  • 提供可视化 UI,支持按服务、操作、时间范围筛选链路,查看 Span 耗时、调用关系;
  • 支持分布式上下文传播,还原跨服务调用链路。

方案架构设计

本方案采用 "Agent 采集 + Collector 转发 + Jaeger 存储 / 可视化" 的经典架构,整体流程如下:

  1. 业务 Java 服务通过 OpenTelemetry Java Agent 实现无侵入自动埋点,生成追踪数据;
  2. 追踪数据通过 OTLP(OpenTelemetry Protocol)协议发送到 OTel Collector;
  3. OTel Collector 对数据进行批处理优化后,转发至 Jaeger 后端;
  4. 运维 / 开发人员通过 Jaeger UI 查看全链路追踪信息,定位问题。
  5. 仅仅作为在测试环境内使用,若上线生产则需增加认证以及ES存储。

二、环境准备

1、镜像准备

为提升镜像拉取速度,本文使用华为云镜像源拉取 OTel Collector 和 Jaeger 镜像,拉取后统一打标为官方标签,避免后续部署命令修改:

bash 复制代码
# 拉取镜像
root@uat:/data/otel#  docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/otel/opentelemetry-collector-contrib:latest
root@uat:/data/otel#  docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jaegertracing/all-in-one:latest 

# 镜像标签
root@uat:/data/otel#  docker tag  swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jaegertracing/all-in-one:latest  docker.io/jaegertracing/all-in-one:latest 
root@uat:/data/otel#  docker tag  swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/otel/opentelemetry-collector-contrib:latest  docker.io/otel/opentelemetry-collector-contrib:latest 

2、端口准备

分布式追踪系统需占用多个端口,需提前检查是否被占用,各端口用途如下:

端口 协议 用途 所属组件
5775 UDP Jaeger 经典协议接收端口 Jaeger
6831 UDP Jaeger Thrift 协议端口 Jaeger
6832 UDP Jaeger Thrift 协议端口 Jaeger
16686 TCP Jaeger UI 访问端口 Jaeger
4317 TCP OTLP gRPC 协议接收端口 OTel Collector/Jaeger
4318 TCP OTLP HTTP 协议接收端口 OTel Collector/Jaeger
14250 TCP Jaeger gRPC 协议端口 Jaeger

执行以下命令检查 TCP/UDP 端口占用情况:

bash 复制代码
root@uat:/data/projects/easewise/easewise-back# PORTS="5775 6831 6832 16686 14250 4317 4318" 
for port in $PORTS; do
  ss -tuln | grep -E ":$port\b" > /dev/null
  if [ $? -eq 0 ]; then
    echo "⚠️  TCP端口 $port 已被占用:$(ss -tuln | grep -E ":$port\b")"
  else
    echo "✅  TCP端口 $port 未被占用"
  fi
done
✅  TCP端口 5775 未被占用
✅  TCP端口 6831 未被占用
✅  TCP端口 6832 未被占用
✅  TCP端口 16686 未被占用
✅  TCP端口 14250 未被占用
✅  TCP端口 4317 未被占用
✅  TCP端口 4318 未被占用
root@uat:/data/projects/easewise/easewise-back# UDP_PORTS="5775 6831 6832"
root@uat:/data/projects/easewise/easewise-back# for port in $UDP_PORTS; do
  ss -tuln | grep -E ":$port\b" > /dev/null
  if [ $? -eq 0 ]; then
    echo "⚠️  UDP端口 $port 已被占用:$(ss -tuln | grep -E ":$port\b")"
  else
    echo "✅  UDP端口 $port 未被占用"
  fi
done
✅  UDP端口 5775 未被占用
✅  UDP端口 6831 未被占用
✅  UDP端口 6832 未被占用
root@uat:/data/projects/easewise/easewise-back# 

三、分布式追踪系统部署

1、部署Jaeger

Jaeger All-in-One 包含了 Collector、Query、Agent、UI 等所有组件,适合测试 / 中小规模生产环境快速部署:

bash 复制代码
docker run --rm -d --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:latest

部署完成后,可通过docker ps | grep jaeger确认容器是否正常运行。

2、部署otel-collector:

bash 复制代码
docker run -d --name otel-collector \
  -p 4317:4317 \
  -p 4318:4318 \
  -v $(pwd)/coll-config.yaml:/etc/otelcol-contrib/config.yaml \
  otel/opentelemetry-collector-contrib:latest 

OTel Collector 负责统一接收各服务的追踪数据,处理后转发至 Jaeger,需先创建配置文件coll-config.yaml:

bash 复制代码
# 完整的 coll-config.yaml(包含 traces + logs 处理)
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:

exporters:
  otlp:
    endpoint: "172.17.0.4:4317"  # 替换为Jaeger容器内网IP
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp]

注意:Jaeger 容器内网 IP 需通过docker inspect jaeger | grep IPAddress查询,替换上述配置中的172.17.0.4。

服务启动后查看日志信息:

bash 复制代码
root@master:/data/otel# docker logs otel-collector 
2026-01-26T07:36:00.584Zinfootelcol@v0.120.0/collector.go:339Received signal from OS{"signal": "terminated"}
2026-01-26T07:36:00.584Zinfoservice@v0.120.0/service.go:323Starting shutdown...
2026-01-26T07:36:00.585Zinfoextensions/extensions.go:68Stopping extensions...
2026-01-26T07:36:00.585Zinfoservice@v0.120.0/service.go:337Shutdown complete.
2026-01-26T07:36:01.427Zinfoservice@v0.120.0/service.go:193Setting up own telemetry...
2026-01-26T07:36:01.435Zinfoservice@v0.120.0/service.go:258Starting otelcol-contrib...{"Version": "0.120.1", "NumCPU": 80}
2026-01-26T07:36:01.435Zinfoextensions/extensions.go:40Starting extensions...
2026-01-26T07:36:01.436Zinfootlpreceiver@v0.120.0/otlp.go:116Starting GRPC server{"otelcol.component.id": "otlp", "otelcol.component.kind": "Receiver", "endpoint": "0.0.0.0:4317"}
2026-01-26T07:36:01.436Zinfootlpreceiver@v0.120.0/otlp.go:173Starting HTTP server{"otelcol.component.id": "otlp", "otelcol.component.kind": "Receiver", "endpoint": "0.0.0.0:4318"}
2026-01-26T07:36:01.436Zinfoservice@v0.120.0/service.go:281Everything is ready. Begin running and processing data.

3、配置服务器启动

以 Java 服务为例,使用 OpenTelemetry Java Agent 实现无侵入自动埋点,无需修改业务代码。

下载javaagent:

bash 复制代码
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.24.0/opentelemetry-javaagent.jar

启动服务:

bash 复制代码
java -javaagent:/data/projects/opentelemetry-javaagent.jar -Dotel.service.name=gateway -Dotel.exporter.otlp.endpoint=http://192.168.119.7:4317 -Dfile.encoding=utf-8 -jar gateway.jar 

参数说明:

  • otel.service.name:服务标识,Jaeger UI 中会按此名称筛选链路;
  • otel.exporter.otlp.endpoint:OTel Collector 的地址(优先用 gRPC 端口 4317);
  • 若仅需追踪数据,可添加-Dotel.logs.exporter=none关闭日志导出,避免冲突。

若为supervisor,服务器启动配置文件:

bash 复制代码
root@uat:/data/projects# cat /etc/supervisor/conf.d/gateway.conf
[program:gateway]
directory=/data/projects/
command=/bin/bash -c "java -javaagent:/data/projects/opentelemetry-javaagent.jar -Dotel.service.name=gateway -Dotel.exporter.otlp.endpoint=http://192.168.119.7:4318 -Dotel.logs.exporter=none -Dfile.encoding=utf-8 -jar gateway.jar"
autostart=true
autostart=true
autorestart=true
startsecs=5
startretries=3
user=root
redirect_stderr=false
stdout_logfile=/data/logs/gateway.log
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=3
stderr_logfile=/data/logs/gateway.err
stderr_logfile_maxbytes=20MB
stderr_logfile_backups=3

4、验证链路采集

访问 Jaeger UI(浏览器打开http://服务器IP:16686):

  1. 在 "Service" 下拉框中选择配置的服务名(如gateway);
  2. 点击 "Find Traces",若服务有请求量,即可看到对应的追踪链路;
  3. 点击某条链路,可查看请求的全链路 Span、各 Span 耗时、调用关系等信息。

具体链路请求信息:

相关推荐
IT研究所16 分钟前
AI-ITR平台如何减少客户问题反复升级?
大数据·运维·人工智能·低代码·自然语言处理·安全架构·企微
BLUcoding19 分钟前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom
AIgorithmGEEK22 分钟前
[Linux]从手写报头到内核套路:序列化、反序列化与自定义协议全链路
linux·运维·服务器·网络·序列化·反序列化
Nil20830 分钟前
leetcode 139单词拆分
linux·运维·服务器
Starry-sky(jing)34 分钟前
BUG: unable to handle kernel paging request 完整排查:dmesg 四要素与三路定罪
linux·运维·服务器·内核·排障
yuniko-n35 分钟前
【JUC】Lock 和 synchronzied 锁
java
mounter62540 分钟前
从硬件互连到操作系统变革:CXL 技术演进与 Linux 内核工程挑战
linux·运维·服务器
西柚小萌新42 分钟前
【LLM&&AI应用开发 八股文】--4.3.Agent智能体(下)
java·开发语言·数据库
北极有牛44 分钟前
cpp学习笔记--常量指针
java·开发语言·算法
zhengqweasd1 小时前
机房托管服务器怎么选硬盘,机械盘和 SSD 托管场景差异
运维·服务器·github