3. Jaeger 架构深度解析:Agent、Collector、Query、UI 组件及数据流
Jaeger 作为云原生链路监控的标准实现,其架构设计遵循“轻量采集 → 异步缓冲 → 后端存储 → 查询展示”的分层原则。理解每个组件的职责与数据流转路径,是构建高可用链路监控体系的基础。
3.1 核心组件与职责
Jaeger 架构由四个主要组件构成,它们各自独立部署,通过 gRPC 或 HTTP 协议通信。
| 组件 | 部署位置 | 核心职责 | 关键协议/端口 |
|---|---|---|---|
| Agent | 与业务应用同机部署(Sidecar 或 DaemonSet) | 接收应用发出的 UDP 数据,批量压缩后转发给 Collector | UDP 6831/6832(Thrift)、gRPC 转发 |
| Collector | 独立集群部署(无状态) | 验证、清洗、索引 Span 数据,写入后端存储 | gRPC 14250、HTTP 14268 |
| Query | 独立集群部署(无状态) | 从存储读取 Trace,提供 API 和 Web 界面查询 | HTTP 16686(UI + API) |
| UI | 与 Query 同进程或独立部署 | 可视化 Trace 拓扑、火焰图、服务依赖关系 | HTTP 16686(Web 页面) |
架构要点: Agent 是唯一有状态(与业务进程绑定)的组件;Collector 和 Query 均为无状态,支持水平扩展,这是 Jaeger 高可用的核心设计。
3.2 数据流全景(端到端链路)
一条完整的 Trace 从用户请求进入系统开始,到 UI 展示结束,经历以下 6 个关键步骤:
- 埋点生成:应用代码通过 OpenTracing/OpenTelemetry SDK 创建 Span,携带 TraceID、SpanID、ParentSpanID。
- Agent 本地缓冲:SDK 通过 UDP 将 Span 发送给本地 Agent,Agent 在内存中做轻量聚合与压缩。
- Collector 批量接收:Agent 通过 gRPC 将批量 Span 推送到 Collector 集群(默认每 1 秒或每 1000 条推送一次)。
- 存储持久化:Collector 将 Span 写入后端存储(Cassandra / Elasticsearch / Badger)。
- Query 检索:用户通过 UI 发起查询,Query 服务从存储中按 TraceID 或标签检索 Span。
- UI 渲染:Query 返回完整 Trace 数据,UI 渲染为时序图、拓扑图或火焰图。
3.3 组件深度解析
3.3.1 Agent:轻量本地代理
- 部署模式:Kubernetes 中作为 DaemonSet 或 Sidecar 运行;物理机中作为独立进程。
- 核心功能:接收 SDK 通过 UDP 发送的 Span,在内存中做 去重、合并、压缩,然后通过 gRPC 转发给 Collector。
- 关键配置:
--processor.jaeger-compact.server-queue-size=10000(队列大小)、--reporter.grpc.host-port=collector:14250。
生产建议: Agent 的 UDP 接收队列不要设置过大(建议 5000~10000),避免内存溢出;同时开启
--reporter.grpc.retry.max=3 保证 Collector 短暂不可用时数据不丢失。
3.3.2 Collector:数据清洗与存储网关
- 无状态设计:Collector 不维护任何持久状态,所有 Span 处理完成后立即写入存储。
- 处理流程:接收 Span → 校验 TraceID/SpanID → 补充服务名/标签索引 → 写入存储。
- 存储适配:通过
--span-storage.type=elasticsearch或--span-storage.type=cassandra切换后端。
3.3.3 Query 与 UI:检索与可视化
- Query 服务:提供 gRPC 和 HTTP 两种 API,支持按 TraceID、服务名、标签、时间范围检索。
- UI 功能:Trace 时序图(Gantt Chart)、服务依赖图(DAG)、火焰图(Flame Graph)、性能统计。
- 依赖分析:Query 通过
--query.dependency.storage-type=elasticsearch读取服务拓扑数据。
3.4 数据流中的关键协议与端口
| 协议 | 端口 | 用途 | 数据格式 |
|---|---|---|---|
| UDP | 6831 | Agent 接收 SDK 的 Thrift 压缩数据 | Thrift Compact Protocol |
| UDP | 6832 | Agent 接收 SDK 的 Thrift 二进制数据 | Thrift Binary Protocol |
| gRPC | 14250 | Agent → Collector 批量推送 | Protobuf |
| HTTP | 14268 | SDK 直接发送给 Collector(无 Agent 场景) | JSON / Thrift |
| HTTP | 16686 | Query 服务(UI + API) | JSON |
3.5 高可用部署架构
在生产环境中,Jaeger 各组件通常以集群方式部署,形成如下高可用拓扑:
3.6 数据流中的关键机制
| 机制 | 说明 | 配置示例 |
|---|---|---|
| 采样策略 | Agent 或 Collector 根据概率/速率决定哪些 Trace 被保留 | --sampler.type=probabilistic --sampler.param=0.1 |
| 批量发送 | Agent 将多个 Span 合并为一个 gRPC 请求,减少网络开销 | --reporter.grpc.batch-size=100 |
| 背压控制 | Collector 处理不过来时,通过 gRPC 流控通知 Agent 降速 | 内置机制,无需配置 |
| 数据持久化 | Collector 写入存储失败时,可配置本地文件缓冲(需插件) | Jaeger v1.35+ 支持 Kafka 作为缓冲层 |
常见陷阱: 如果 Agent 与 Collector 之间的 gRPC 连接中断,Agent 默认会丢弃超出队列的 Span。生产环境建议在 Agent 与 Collector 之间部署 Kafka 作为可靠缓冲层,避免数据丢失。
3.7 组件通信协议对比
| 通信路径 | 推荐协议 | 优势 | 劣势 |
|---|---|---|---|
| SDK → Agent | UDP Thrift | 零阻塞、低延迟、对业务无影响 | 可能丢包(UDP 不可靠) |
| Agent → Collector | gRPC | 批量、压缩、流控、重试 | 需要建立 TCP 连接 |
| SDK → Collector | HTTP/gRPC | 无需 Agent,简化部署 | 增加业务进程开销 |
| Collector → 存储 | HTTP/gRPC | 标准化写入接口 | 依赖存储侧性能 |
| Query → 存储 | HTTP/gRPC | 支持复杂查询 | 查询延迟受存储影响 |