追踪数据发给后端的路上会在哪里丢?BatchSpanProcessor 的队列满了会怎样、会不会拖慢业务?后端慢一点、挂一会儿,丢多少?进程退出时队列里的 span 怎么办?这篇用 OpenTelemetry Python SDK 和自己写的 OTLP 接收端逐项量出来。
接收端收到 4096 个 span,没收到(丢了)1904 个;收到的序号范围 0~5999;接收端一共处理了 8 个请求;产生 span 的调用(start 到 end)耗时中位数 89 µs、p99 345 µs、最大 6.40 ms;SDK 的 warning:“Queue full, dropping Span.…”× 1 收到的序号区间(连续的一段算一个区间):0-1023,1494-2005,3020-3531,3952-5999
持续产生速度超过导出能力时,队列装满后丢弃 span,业务线程几乎不受影响。
max_queue_size | 收到 | 丢了 | 收到的序号范围 | 接收端处理的请求数 ---------------+------+------+---------+---------- 512 | 2560 | 3440 | 0~5999 | 5 2048 | 4096 | 1904 | 0~5999 | 8 20000 | 6000 | 0 | 0~5999 | 12 接收端每次请求处理 1.5 s、一批最多 512 个 span,所以持续的处理能力有上限;产生速度超过它,队列装不下的 span 就被丢弃,队列越大能缓冲的越多,但内存也随之增加
队列越大缓冲越多,但占内存;默认 2048 只够吸收短暂的突发。
max_queue_size | 收到 | 丢了 | 收到的序号范围 | 请求数 | 平均每个请求体 | SDK warning 条数 ---------------+-------+------+---------+-----+---------+--------------- 2048 | 3072 | 6928 | 0~9999 | 6 | 38 KB | 1 20000 | 10000 | 0 | 0~9999 | 20 | 37 KB | 0 产生 span 的线程比导出线程快,队列装满之后新来的(或最老的)被丢;队列够大时突发能被吸收
瞬间产生的 span 比队列大时,多出来的被丢掉。
故障方式 | 收到 | 丢了 | 收到的序号范围 | SDK 的 warning(去重 × 次数) ---------+------+----+---------+---------------------------------------------- (a)503 | 2400 | 0 | 0~2399 | Transient error Service Unavailable enco… × 3 (b)停掉再重启 | 2400 | 0 | 0~2399 | Transient error HTTPConnectionPool(host=… × 3
导出器的重试加队列可以吸收几秒的接收端故障。
收到 3800 个,丢了 2200 个;收到的序号区间:1216-1727,2712-5999;SDK 的 warning:“Transient error Service Unavailable encountered while exporting spans …”× 9;“Failed to export spans batch due to timeout, max retries or shutdown.…”× 2;“Queue full, dropping Span.…”× 2
故障超过导出超时和队列容量时,整批导出失败被丢掉,队列也会溢出。
结束方式 | 收到 | 丢了 | 接收端处理的请求数
---------------------+------+------+----------
(a)正常退出 | 1000 | 0 | 2
(b)os._exit(0) | 0 | 1000 | 0
(c)产生完 1 s 后 SIGKILL | 512 | 488 | 1
队列里还没导出的 span,进程不经过 shutdown 就退出(os._exit、被杀)就永远丢了;正常退出时 SDK 的 atexit 钩子会把队列刷出去
ERRORS {}不经过 shutdown 的退出会丢掉队列里的所有 span。