拆开 Hical:中间件洋葱模型怎么做到连续 N 个同步中间件只分配一次协程帧?

[Hical] 中间件洋葱模型怎么做到"连续 N 个同步中间件只分配一次协程帧"? 本专栏文章:拆开 Hical · 第 3 篇 上一篇文章讲了 Router 的 dispatchSync——当 handler 是同步的,跳过协程帧分配。同样的思路也应用在中间件上。 大多数框架的中间件是"一层一个协程"——3 个中间件 = 3 个协程帧 = 3 次堆分配。但 Hical 问了一个问题:如果 N 个中间件都是同步的(不用 co_await),为什么不能把它们合并成一个协程帧? 答案是:可以。而且 Hical 实现了。 1. 先理解洋葱模型 1.1 标准中间件的三个角色 一个 HTTP 请求经过中间件管道时,有三种类型的操作: 1 2 3 请求进来 ──→ before1 ──→ before2 ──→ handler ──→ after2 ──→ after1 ──→ 响应出去 ↑ ↑ ↑ ↑ 前置拦截 前置处理 后置修改 后置处理 Before:在 handler 之前执行。可以拦截请求、直接返回响应(如认证失败返回 401) Handler:核心业务逻辑 After:在 handler 之后执行。可以修改响应头(如加安全头、压缩 body) 1.2 传统方案:一层一个协程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // 全异步中间件链:N 个中间件 = N 个协程 lambda MiddlewareNext makeChain(asyncHandler1, asyncHandler2, asyncHandler3, finalHandler) { // 从内到外构建 auto inner = [h3, finalHandler](req) -> Awaitable<HttpResponse> { co_return co_await h3(req, finalHandler); }; auto middle = [h2, inner](req) -> Awaitable<HttpResponse> { co_return co_await h2(req, inner); }; auto outer = [h1, middle](req) -> Awaitable<HttpResponse> { co_return co_await h1(req, middle); }; return outer; } 3 个协程 lambda → 3 个协程帧 → 3 次堆分配。 ...

August 10, 2026 · 6 min · 1099 words