基于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 耗时、调用关系等信息。

具体链路请求信息:

相关推荐
进阶小白猿2 小时前
Java技术八股学习Day25
java·jvm·学习
组合缺一2 小时前
Solon AI Remote Skills:开启分布式技能的“感知”时代
java·人工智能·分布式·agent·langgraph·mcp
weixin_436525072 小时前
若依多租户版 - modules中创建子模块
java·服务器·前端
jiunian_cn2 小时前
【Redis】Redis入门——分布式架构演进及Redis基本特性初识
redis·分布式·架构
EverydayJoy^v^2 小时前
RH134简单知识点——第8章——管理存储堆栈
linux·运维·5g
板面华仔2 小时前
Linux基础(下)——工作中常用命令总结
linux·运维·服务器
刃神太酷啦2 小时前
Linux 基础 IO 收官:库的构建与使用、进程地址空间及核心知识点全解----《Hello Linux!》(11)
java·linux·c语言·数据库·c++·算法·php
猿小羽2 小时前
Spring AI + MCP 实战:构建标准化、可扩展的 AI Agent 架构体系
java·spring boot·llm·架构设计·ai agent·spring ai·mcp
独自破碎E2 小时前
Spring Boot的多环境配置
java·spring boot·后端