
从 Jaeger 到 OpenTelemetry Collector我把一套可观测性管道拆成了三层搞可观测性这件事我以前走过一条很笨的路。服务一多大家最容易干的事就是把 trace 一股脑往 Jaeger 里打。刚开始看着挺爽接入简单、页面也能查出了问题还能顺手点开链路追一下。结果业务量一上来Collector、消息队列、存储后端全开始互相拖后腿最后排障系统自己先成了瓶颈。我后来受不了了索性把整套链路追踪管道拆成三层接入层、处理层、落库层。改完之后采集配置清楚了扩容也不再是一锅粥最重要的是谁该降采样、谁该保真、谁该走低成本存储终于能分开管了。这篇不讲抽象概念我直接把我这套拆法和踩坑过程摊开讲。为什么我不想再让 Jaeger 一把梭了Jaeger 本身没什么问题问题在于很多团队拿它当“全能终点站”。接收、处理、采样、转发、存储全堆在一条链路里前期省事后期特别难调。你一旦遇到以下情况基本就该警觉了新接一个服务就得改一堆采集配置某个高流量服务把整个 trace 后端拖慢想给支付链路保留更多数据却只能全局改采样率开发、测试、生产链路混在一起排查时全靠肉眼筛我当时最烦的是第三个问题。核心交易链路我想多留一点推荐和埋点流量我想少留一点但原来的结构根本不给我这种粒度。最后只能用同一把尺子量所有服务结果要么成本太高要么信息不够。我最后拆成了哪三层我的做法很直接把可观测性管道拆成“接入层、处理层、落库层”。听起来像套话但真的拆开以后后面的治理工作会轻很多。第一层接入层只负责稳定收数据这一层我只让它做一件事老老实实接 OTLP不掺杂复杂逻辑。应用侧的 SDK 统一把 trace 发给一个入口 Collector入口层只负责协议兼容、基础限流和 batch不做重采样、不做复杂路由。因为入口层离业务最近最怕配置过重把采集本身搞不稳定。我现在一般会这么配receivers:otlp:protocols:grpc:http:processors:memory_limiter:check_interval:1slimit_mib:1024batch:send_batch_size:8192timeout:2sexporters:otlp/processing:endpoint:otel-processing:4317tls:insecure:trueservice:pipelines:traces:receivers:[otlp]processors:[memory_limiter,batch]exporters:[otlp/processing]这层的目标就两个字别炸。只要业务数据能稳稳接进来后面你要怎么采样、怎么路由都还有操作空间。第二层处理层专门做采样、过滤和路由真正复杂的逻辑我全放在第二层。这一层是整条管道里最值钱的部分因为策略基本都在这。比如错误链路 100% 保留慢请求优先保留健康检查、轮询、埋点流量降采样按service.name、环境、业务域路由到不同后端我现在比较常用的一段配置是这样的processors:tail_sampling:decision_wait:10snum_traces:50000expected_new_traces_per_sec:2000policies:-name:error-tracestype:status_codestatus_code:status_codes:[ERROR]-name:slow-tracestype:latencylatency:threshold_ms:1200-name:normal-traffictype:probabilisticprobabilistic:sampling_percentage:15routing:from_attribute:service.nametable:-value:payment-serviceexporters:[otlp/core]-value:order-serviceexporters:[otlp/core]-value:recommendation-serviceexporters:[otlp/lowcost]-value:metrics-gatewayexporters:[otlp/lowcost]这层的关键不是“规则写得多复杂”而是你终于能把不同业务的观测价值区分开了。核心链路保真噪声流量控成本团队之间也不会再因为“一刀切采样率”扯皮。第三层落库层按价值决定存哪里以前我最容易忽略的就是存储层其实也该分级。不是所有 trace 都值得进同一套后端。我的做法是核心链路、错误链路进查询体验更好的主后端普通业务链路走低成本存储或短保留周期测试环境和回归链路单独隔离避免污染生产数据这样拆完以后Jaeger 不再是唯一出口而是“其中一个高价值查询后端”。这感觉完全不一样。说白了Jaeger 该做的是让你查关键链路不是替你兜所有历史垃圾流量。拆完之后我得到的最直接收益这个结构真正落地后我最明显的感受有 4 个。1. 扩容终于能按瓶颈来不是全链路一起加机器以前一旦 trace 压力变大大家下意识就是给整套系统加资源。现在不一样。入口层 CPU 紧张就扩入口处理层队列积压就扩处理层落库慢了就单独调后端。问题位置一下就清楚了不用整条链路一起跟着“陪跑”。2. 采样策略终于能按业务谈而不是按平台拍脑袋定之前平台侧最常见的话术是“大家统一采 20% 吧。”这句话听起来公平实际上很偷懒。订单和支付链路的观测价值怎么可能跟埋点上报一个级别。拆层之后我终于能把核心业务、高频噪声、测试环境分开定策略。沟通成本反而更低因为每个决策都有边界。3. 故障隔离明显好很多有一次推荐服务突然 trace 暴涨以前这种情况会连带把整个查询后端拖慢。现在因为它走的是低成本出口核心支付链路完全没被影响。这个收益平时感觉不到真出事的时候特别值。4. 接入新服务快了很多以前新服务接入 trace经常要顺手改采样、改路由、改存储映射。现在接入层只认 OTLP新服务默认先进公共入口后续要不要细分策略再在处理层单独加规则。新接一个服务的改动面小了不少。这套拆法最容易踩的 4 个坑1. 接入层逻辑写太重这个坑我一开始就踩了。我曾经把过滤、采样、属性清洗全塞在入口 Collector结果入口层一抖所有服务一起掉 trace。后来我才意识到入口层最重要的是稳不是聪明。2.service.name没治理好路由规则等于白写很多团队的 SDK 配置不统一最后出现一堆乱七八糟的服务名order-serviceorder_serviceorderServiceorder-prod这种情况下你做按服务路由最后只会把自己绕晕。我的建议很直接先治理命名再谈分流。3. 处理层只做采样不看队列和回压处理层不是配置中心它本质上还是一个高吞吐数据面。如果你只盯采样规则不看queue_size、dropped_spans、export 超时这些指标迟早会在流量高峰时翻车。我现在会固定盯这些指标curl-shttp://otel-processing:8888/metrics|grep-Equeue|dropped|exporterkubectltoppod-nobservability|grepotel-processing kubectl logs-nobservability deploy/otel-processing--since10m|grep-Eitimeout|retry|drop4. 落库层不做环境隔离开发、测试、生产 trace 混在一套后端里看起来省事实际上很吵。你排一个生产慢请求结果列表里全是测试流量。等真出线上故障时这种噪声会特别烦。如果条件允许环境隔离至少要做到索引级、租户级别混着放。如果你现在也想改我建议按这个顺序来别想着一周内把可观测性体系重构完那样大概率会把自己搞崩。我的建议是分三步先把入口 Collector 单独抽出来只负责接 OTLP再补一个处理中间层把采样、过滤、路由迁过去最后再按业务价值拆存储出口和保留周期这个顺序的好处是风险可控而且每一步都能单独验证。最怕的是一上来就同时改 SDK、Collector、采样和后端存储。改动一多出了问题你根本不知道是哪层惹的祸。写在最后我现在越来越觉得可观测性平台和业务系统一样也得做分层。你要是把接入、处理、路由、落库全揉成一坨前期可能快后期一定乱。Jaeger 不是不能用而是不该一个人扛完整个观测管道。从 Jaeger 走向 OpenTelemetry Collector不只是换个组件名字更重要的是把“采多少、留哪些、存到哪、谁优先”这些事情重新分层。这一步做对了后面你再谈成本、稳定性和排障效率才有底气。