第 6 章 层间语义:异步编程与错误处理


第 6 章 · 层间语义:异步编程与错误处理

章节摘要:本章离开进出两半程,看层与层之间的"胶水"——async/await 的传播规则、请求上下文如何跨越异步边界、全局错误事件怎么接日志、进程级异常与优雅退出怎么兜。这些语义决定服务在异常路径上的可靠性。

一条主线:一次超时引发的排查

本章主线从一封工单开始:某接口偶发 502,日志却一片干净——没有异常、没有慢查询记录,仿佛什么都没发生。排查这条线索要动用本章的全部知识:先确认异常有没有真的沿 Promise 链冒上来(6.1 的 await 语义与传播规则),再确认请求级上下文(请求 ID、用户)在异步边界上有没有断掉(6.1 的异步上下文方案),然后给全局错误事件接上结构化日志让"看不见的异常"显形(6.2),最后查到根因是一个未 await 的 Promise 静默 rejection——顺带补齐进程级兜底与优雅退出(6.3)。工单是虚构的,排查路径是真实的:这四站就是 Koa 异步可靠性知识的主干。

沿途站点

  • 6.1 async/await 与异步上下文——await 的传播与并行规则(Promise.all 的正确用法)、断 await 的三种事故形态、用 AsyncLocalStorage 实现跨异步边界的请求上下文。
  • 6.2 全局错误监听与日志集成——把 app.on('error') 接进结构化日志体系,请求 ID 全链路贯穿的设计,错误分级与告警的接线方式。
  • 6.3 未捕获异常与进程稳定性——uncaughtException 与 unhandledRejection 的处理策略、优雅退出编排、长期运行下的内存与句柄守则。

拐点与结论

本章拐点在 6.1 的一个反直觉事实:Koa 里写错异步,最常见的症状不是报错,而是"安静"——漏了 await 的 Promise 在链外默默 rejection,响应照常出去,日志毫无动静。多数人的直觉是"错了总会报错吧",事实证明恰恰相反。由此得出本章结论:异步可靠性不靠自觉靠结构——所有异步留在链上(await 纪律)、断链的兜底放在进程级(rejection 事件)、异常的痕迹靠结构化日志(requestId 贯穿),三件套齐了,"偶发 502 但日志干净"这类幽灵问题才有抓手。

四站的知识依赖如下图。

图 6-0:异步可靠性三件套的防护纵深

图 6-0:异步可靠性三件套的防护纵深

异步问题的排查工具箱

这一章的知识在排查现场怎么用?给一个顺序清单。第一步,复现并分类:稳定复现的多半是逻辑错误(断 await、吞异常),偶发的先怀疑时序与并发——这时直接翻到 6.1 的三种漏 await 事故形态对号。第二步,按 reqId 拉链路:用 6.2 的结构化日志把同一次请求的所有痕迹拉到一起,看异常在哪一层最后留下记录。第三步,分层验证:临时在可疑层的进层与出层各加一条 debug 日志,观察它进没进、出没出——出层日志缺失就是截停或断链的铁证。第四步,进程级收网:如果日志全程干净但故障仍在,开 6.3 的 unhandledRejection 记录跑一段时间,链外的 rejection 会自己现形。这四步覆盖了异步类故障九成以上的排查路径。

读完你应该

  1. 能判断任一异步代码在 Koa 链上是否可靠,指出漏 await 的位置与后果;
  2. 能用 Promise.all 正确并行化独立的异步调用,说清与串行 await 的耗时差异;
  3. 能用 AsyncLocalStorage 建立请求上下文,让日志自动带上请求 ID 与用户信息;
  4. 能把 app.on('error') 接进结构化日志与告警,按错误级别分级处理;
  5. 能编写进程级 rejection 与 exception 兜底,并实现一套优雅退出编排。

下一章的接力

服务自身的语义立稳了,下一章给洋葱套上防护层:常见的 Web 攻击面、安全响应头与 CSRF 对策、JWT 鉴权中间件的完整实现、HTTPS 与输入验证——安全不是功能,是层。

作者与出处
原作者:灏天文库
来源:平台策划编纂
整理人: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U