
适合谁收藏需要按证据链完成 HTTP 现场排障的工程师。需要复核 32 个源码文件覆盖范围的人。准备把整套 HTTP 工程迁移到目标运行时并重新验收的读者。本篇位置综合收束第 1/2 篇主系列第 27/28 篇。现场问题HTTP 不通时最慢的办法是从第一行代码重新读。最快的办法是先确认故障停在哪一层再用状态、错误码、原始报文、指标和连接快照交叉验证。同一个“没有响应”可能是端口未监听、连接槽没激活、Header 未完整、Body 长度不足、Builder 拒绝超限消息或者 TCP_Write 失败。先给结论排障顺序固定为先连接证据再消息边界再角色状态机最后业务结果。任何层没有证据就不要越层猜测。读图重点这张图只压缩本篇的判断路径。读图时先找“无法连接”对应的输入边界再沿着“连接快照、缓冲区和复用策略”检查状态怎样推进最后用“清理时机与 pipeline 越界”确认输出是否已经形成验收证据。把对象和边界分开对象或阶段工程职责现场观察点无法连接ServerState、监听句柄、NBS error监听地址、端口和使能连接后无响应槽位状态、RxMessage、Header 结束位置Read 与半包边界返回 400E_HttpError、原始 HeaderHost、长度、TE/CL 冲突Client 一直 BusyClientState、Tx/Rx 长度、超时发送完成和响应边界偶发串包连接快照、缓冲区和复用策略清理时机与 pipeline 越界一次现场排障应该怎样落笔假设现象是“Client 一直 Busy八秒后超时”。先不要改超时值按下面顺序取证看 ClientState 是否已经越过 Connect。如果没有问题仍在地址、端口或 TCP 服务。看 TxMessage 和发送偏移是否达到完整请求长度。如果没有检查 Write 状态和 NBS error。看 RxMessage 是否出现状态行和 Header 结束符。如果只出现一部分继续追接收分片。看 Content-Length、chunked 和 Connection 三个边界字段怎样组合。如果边界不清楚Parser 不应完成。最后把错误码、Metrics 增量和原始响应放在一起判断这是超时、协议错误还是业务状态码。这五步的价值在于每一步都能排除一层。只要证据链停在某一步后面的业务代码就不应成为首要怀疑对象。固定一张故障记录表记录项必须保留的内容用来排除什么触发输入URL、方法、Header、Body 与触发时刻输入变化和重复执行连接证据目标地址、端口、句柄、连接状态与 NBS error监听、路由和底层连接故障消息证据原始 Tx/Rx、累计长度、Header 结束位置半包、粘连和长度不一致角色状态Server/Client 状态、槽位、超时阶段状态机未推进或清理过早协议结果HTTP error、状态码、响应 Header 与 Body协议错误和业务结果混淆回归结果同一输入修复前后差异、计数变化修复是否真正命中根因记录时不要只截最终错误画面。一次故障至少要保留触发前状态、首次出现异常的周期和恢复后的下一笔正常事务。这样才能区分“本次请求失败”“错误已锁存但事务已恢复”和“资源仍未释放”三种情况。若修改后只用另一条 URL、另一种连接策略或另一台服务验证就没有完成同场景回归原问题仍可能存在。同场景回归还要检查副作用失败计数是否只增加一次、连接槽是否回到可接入状态、下一笔正常请求是否复用了干净缓冲区、Client 的 Done/Error 脉冲是否只持续约定周期。主现象消失但这些副作用仍在说明修复只绕过了故障入口没有恢复事务生命周期。从协议约束到代码职责协议约束排障顺序固定为先连接证据再消息边界再角色状态机最后业务结果。任何层没有证据就不要越层猜测。 这条结论先限定消息什么时候成立再限定哪个角色可以消费结果。若绕过协议边界直接驱动业务半包、超时、重复执行和连接残留就会进入应用层。工程抽象E_HttpError把协议错误放在 10 到 18把 TCP 与超时错误放在 100 以上。这个分区使排障脚本和在线变量可以快速判断问题属于协议层还是传输层。Metrics 负责回答“发生了多少次”Snapshot 负责回答“最后一次发生在哪个槽位、什么状态、什么路径”。两者缺一不可只有计数没有现场只有现场没有趋势。无法连接工程职责是“ServerState、监听句柄、NBS error”。它不能只停留在命名层面运行时必须能通过“监听地址、端口和使能”观察到输入、状态或结果否则这一层即使有代码也没有形成可验证边界。连接后无响应工程职责是“槽位状态、RxMessage、Header 结束位置”。它不能只停留在命名层面运行时必须能通过“Read 与半包边界”观察到输入、状态或结果否则这一层即使有代码也没有形成可验证边界。返回 400工程职责是“E_HttpError、原始 Header”。它不能只停留在命名层面运行时必须能通过“Host、长度、TE/CL 冲突”观察到输入、状态或结果否则这一层即使有代码也没有形成可验证边界。Client 一直 Busy工程职责是“ClientState、Tx/Rx 长度、超时”。它不能只停留在命名层面运行时必须能通过“发送完成和响应边界”观察到输入、状态或结果否则这一层即使有代码也没有形成可验证边界。偶发串包工程职责是“连接快照、缓冲区和复用策略”。它不能只停留在命名层面运行时必须能通过“清理时机与 pipeline 越界”观察到输入、状态或结果否则这一层即使有代码也没有形成可验证边界。程序单元本篇主证据来自E_HttpError.st中以TYPE E_HttpError为定位点的连续源码。这里不是为了展示语法而是把协议约束落到确定程序单元输入先进入结构体或缓冲区状态机只在本周期处理可确认的部分长度和结束条件决定能否前进错误码与指标负责把失败原因带出对象边界。这样一来“排障先分层再看代码。”可以在代码、在线变量和外部报文之间逐项对照而不是依赖经验猜测。本篇核心源码片段下面两段代码来自同一个真实文件E_HttpError.st以TYPE E_HttpError为中心连续截取没有改写变量、删除分支或用伪代码替代。第一段用于确认入口与前置条件第二段用于确认状态、边界和输出。核对时重点看“ServerState、监听句柄、NBS error”怎样进入对象以及“清理时机与 pipeline 越界”怎样证明本次处理已经结束。若两段之间的连续关系无法解释“修复完成要用同一输入做回归。”就不能把局部代码截图当成实现证据。片段一入口、声明与前置条件TYPE E_HttpError : ( iNoError : 0, iNeedMoreData : 1, iInvalidArgument : 2, iBufferTooSmall : 3, iInvalidStartLine : 10, iInvalidHeader : 11, iMissingHost : 12, iDuplicateHost : 13, iInvalidContentLength : 14,这一段先回答对象在什么输入和状态下开始工作。阅读时要核对变量的初值、长度上限和启动条件不能只看某个布尔量是否变成 TRUE。片段二状态推进、边界与输出iTransferEncodingContentLength : 15, iBodyTooLarge : 16, iChunkedDecodeFailed : 17, iUnsupportedTransferEncoding : 18, iTcpClientFailed : 100, iTcpServerFailed : 101, iTcpReadFailed : 102, iTcpWriteFailed : 103, iTimeout : 104, iQueueFull : 105 ) INT; END_TYPE第二段继续展示同一连续源码范围。把它与第一段合起来才能判断输入怎样被锁存、状态何时推进、边界何时满足以及错误出口是否保留了足够诊断信息。验证路径场景操作通过口径问题可复现固定输入和连接策略错误码稳定一致问题可定位状态、报文和快照指向同一层不依赖猜测修复可回归对应离线或真机用例重新通过旧问题不再出现恢复可确认下一次正常事务完成状态和计数重新闭环场景 1问题可复现先把 URL、方法、Header、Body、连接复用方式和触发节拍固定下来再连续执行至少三次。每次都记录首次异常周期的角色状态、E_HttpError、NBS error、原始 Tx/Rx 和相关 Metrics 增量。只有错误稳定落在同一层、同一出口才算把偶发现象变成可分析的问题如果错误位置漂移应先排查残留缓冲区、未释放句柄或重复触发。场景 2问题可定位定位不是找到一个可疑变量而是让三类证据互相印证。例如ClientState停在接收阶段时RxMessage应显示当前累计报文连接快照应保留对应句柄和槽位错误码则应说明是等待更多数据还是已经超时。三者指向同一消息边界后再进入代码任何一项矛盾都说明取证时刻或状态清理存在问题。场景 3修复可回归修复后必须原样重放导致故障的输入和连接策略不能换 URL、缩短 Body 或改成短连接来绕过问题。同时补一条相邻边界用例确认修改没有破坏正常路径。通过条件包括原错误不再出现、完成或错误脉冲只产生一次、计数只增加一次并且相关句柄和槽位按预期回收。场景 4恢复可确认故障用例结束后立即发送一笔已知正常事务检查 Server 连接槽是否重新可用、Client 是否从空闲态重新启动、接收缓冲区是否为空以及成功计数是否按一笔事务增长。正常响应出现但旧错误仍锁存在当前结果区或者下一笔请求继承了上一次 Body都不能算恢复完成。常见误判看到 400 就先改业务路由没有检查 Host、长度和 TE/CL 冲突。只记录错误计数不保留最后状态、槽位和原始报文问题无法复盘。修复后换一套输入验证原故障场景没有真正完成回归。这些误判的共同点是拿一个局部现象替代完整事务。定位时必须回到本篇的输入、状态、边界和输出四个坐标并用相同输入完成回归。这一篇你最该记住排障先分层再看代码。错误码、原始报文和快照必须互相印证。修复完成要用同一输入做回归。系列导航系列CodeSys HTTP 系列教程第 27/28 篇。阶段综合收束职责线位置 1/2。上一篇第26篇下一篇第28篇发布顺序基础认知 - Server - Client - 完整源码加更 - 综合收束。