订单请求完成意味着业务工作已经返回,不意味着后台 Batch 队列已排空。进程退出前调用 flush、正常 shutdown 与强制终止,有什么可观测的差异?本篇把“生成三条”“出口报告成功”“本地 HTTP 端点收到三条”分开记录,而不把它们统称为已落库。

完成信号的范围

阶段 能说明 不能说明
span.end() Span 的结束逻辑已执行 Batch 已取出队列
forceFlush().join(limit) 在期限内等待已有处理器完成 超时后结果必然失败或服务器持久化
shutdown().join(limit) 处理器关闭路径得到结果 Collector 或后端可查询
测试端点收到 protobuf HTTP 路径确实有网络接收 数据会长期保留

固定 SHA 的 SdkTracerProvider.forceFlush 组合处理器结果;BatchSpanProcessor.forceFlush 通知 worker 排空当前队列,worker flush 循环 导出队列里的数据,然后完成对应 result。shutdown 先 flush 后关 exporter,二次调用在该处理器层直接返回成功。它不能恢复上一篇已经因队列满而被丢弃的 Span。

CompletableResultCode.join 最多等待给定时长;超时返回的是原结果对象,并不会自动把它标记为失败,要另外检查 isDone() 和 isSuccess()。上游 BatchSpanProcessorTest.shutdownFlushes 检查正常关闭会 flush;上游 testQueueSizeSmallerThanMaxBatchWithForceFlush 检查未达批量阈值仍可导出。这是对固定源码及上游测试的静态阅读,本机运行事实在下一节。

正常退出与强制退出

ExitTraceProducer 是教学子进程:用 Batch 配置 maxExportBatchSize=16、scheduleDelay=1h,生成三条 Span 后不依赖短期定时触发导出。正常路径显式 forceFlush().join(5s) 与 shutdown().join(5s),子进程 exit 0;Lab11Test 的本地 HTTP 接收端解析 OTLP protobuf,新增三条。另一个全新子进程生成三条后调用 Runtime.getRuntime().halt(0):绕过清理路径,父测试确认端点新增零条。该强制退出只针对教学环境的批量参数和此次运行,不能外推为“所有异常退出必丢三条”;如果 Span 已在退出前导出,结果会不同。

独立的限时反例使用闩锁卡住 Batch worker 内的教学 exporter:在 exporter 已进入的屏障之后,forceFlush().join(100ms) 返回但 isDone() 仍为 false;放行后 join(5s) 返回 success。这里的 exporter 只是本地阻塞替身,不是第 10 篇的网络出口;测试用它隔离“等到超时”与“异步执行最终完成”两个状态。

运行 JAVA_HOME=/tmp/otel-20260930/jdk-extract/usr/lib/jvm/java-21-openjdk-amd64 ./mvnw -q -pl sdk-labs -Dtest=Lab11Test test,真实摘要:

1
LAB11 normal=generated:3,http-received:3 forced=generated:3,http-received:0 boundedFlush=incomplete-then-success

HTTP 接收端只回 200,既没有 Collector 处理器、持久化,也没有后端查询。第 10 篇还表明 HTTP 200 可能对应 protobuf 的部分拒收;本篇端点没有发送部分成功响应,因此这里“收到三条”严格限定为教学端点解析出三条。

误解与练习

“join(100ms) 返回就表示 flush 成功”不成立:必须查结果状态。“Runtime.halt(0) 返回码为零就表示遥测已发完”也不成立:本次仍有三条未抵达测试接收端。“flush 成功等于后端可查询”缺少 Collector、后端与查询证据。

练习一。 保持相同两个子进程,把 Batch 阈值调成 1,再重跑。记录强制退出前测试端点接收数是否变化,不要把原有的零条结论当作所有配置的必然结果。

练习二。 在限时等待反例中把 join(100ms) 后的断言改成直接断言 isSuccess(),确认为何断言失败;用 CompletableResultCode.join 的实现解释失败和超时未完成的差别。

导航与参考资料

09 队列与丢弃 · 10 OTLP/HTTP · 当前篇:11 Flush 与 Shutdown · 12 Instrument 选择。

参考资料:固定 SHA c25c0a0ee0da01ab2f74ba83052d1c249ed57020 的 SdkTracerProvider、BatchSpanProcessor、CompletableResultCode 与上游测试(固定链接见正文);本地记录 examples/opentelemetry-java/evidence/11/RUN.md。