先把当时的情况摆出来。OTel Collector 0.110 部署在 2C4G 的边缘节点,memory_limiter 限制 512MiB,流量高峰后 span 数量少了四成,Collector 自身没有 OOM,日志里只有一行 soft limit exceeded,后端 Tempo 看不到告警。
真正麻烦的地方在于,几个原因的现象几乎一样。memory_limiter 触发后直接丢数据而不是背压。还有一种是batch processor 队列过大,先把内存撑满。
不容易想到的是,sending_queue 没开持久化,重启即丢。还有一种情况,采样率在前端已固定,Collector 只能整批丢。
先看 Collector 的限流相关指标
curl -s http://localhost:8888/metrics | grep -i memory_limiter
再往下确认 batch 和 queue 的配置
grep -A6 'batch:' config.yaml
然后把 limit 提到 1GiB 并开启持久化队列
python -c "print('sending_queue:\n storage: file_storage')"
压测后对比入口与出口的 span 计数
curl -s http://localhost:8888/metrics | grep -E 'receiver_accepted_spans|exporter_sent_spans'
怎么算真的好了,看的是同一批现象。压测期间入口和出口的 span 计数差值控制在 1% 以内,soft limit 日志不再出现,Tempo 里能查到完整的调用链。
这里还有个坑。memory_limiter 的语义是丢数据保进程,适合边缘但不适合审计链路;要么提高内存并持久化队列,要么在前端降采样,不能只看进程还活着。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
