Skip to content

Next.js 高级架构

Next.js 长耗时任务、后台任务和连接池如何治理?

请求处理函数不是天然的任务系统,长任务必须从页面请求中拆出,并根据运行时治理连接和重试。

适合阶段:资深全栈 / 稳定性面核心能力:Queue · Serverless · DB

面试官想考什么

  • Route Handler 里能不能启动一个不 await 的后台任务? 考察平台生命周期。
  • Serverless 如何避免数据库连接爆炸? 考察连接池。
  • 长任务失败后怎么恢复? 考察队列和幂等。
  • 页面如何展示任务进度? 考察异步 UX。

一句话回答

text
Next.js 请求函数只负责校验并创建 job,长任务交给有持久化状态和重试策略的队列/Worker;数据库连接按运行时采用池化或代理,任务和副作用用幂等键保护,页面通过查询、SSE 或 WebSocket 展示状态。

面试回答详解

1. 请求与任务分离

text
POST /jobs -> validate/auth -> create job -> return 202 + jobId
worker -> execute -> checkpoint -> complete/fail
UI -> poll/subscribe -> render status

不要依赖请求返回后进程仍然存活。Serverless 可能冻结或终止实例,Edge 也有 API 和时长限制。

2. 任务状态

至少区分 queued、running、retrying、succeeded、failed、cancelled、expired。状态转换要有版本或乐观锁,避免两个 worker 同时执行。

3. 重试与幂等

瞬时网络错误可退避重试,业务拒绝不能无限重试。每个 job 和外部副作用都有 idempotency key;重试前读取 checkpoint 或下游状态,避免重复写入。

4. 连接池策略

  • Serverless:优先托管连接池、数据库代理或 HTTP 数据接口,限制并发。
  • 长生命周期 Node:复用进程级连接池,但要处理热重载和优雅关闭。
  • Edge:选择兼容 Edge 的网络访问方式,不假设原生 TCP 驱动可用。

连接数预算应按实例并发、区域数和最大扩容计算,而不是只看单机。

5. 页面体验和观测

创建 job 后立即返回状态页,支持刷新、取消、重试和下载结果。记录 queue wait、run time、attempt、worker、连接等待、失败原因和最终业务结果。

可直接背诵的 30 秒回答

text
长任务不能靠 Route Handler 返回后继续跑,我会先创建带幂等键的 job,返回 jobId,再由队列和 Worker 执行并持久化状态。数据库连接按 Serverless、Node、Edge 分别选择连接池、代理或兼容驱动。前端用轮询或流订阅展示 queued/running/succeeded/failed,重试、取消和副作用都要可恢复。

扩展知识

轮询与推送

  • 轮询:实现简单、适合低频状态和跨网络环境。
  • SSE/WebSocket:实时性好,但连接、重连、代理和扩缩容更复杂。
  • 两者都应以持久化 job 状态为权威来源。

面试官追问链

追问一:void runTask() 为什么不可靠?

  • 考察点:运行时生命周期。
  • 回答方向:平台可能在响应后冻结或终止实例,异常也无法可靠重试;应交给持久化队列。

追问二:任务取消如何做到?

  • 考察点:协作式取消。
  • 回答方向:写入 cancel_requested,worker 在阶段边界检查 signal,无法立即终止时仍要标记最终状态并停止后续副作用。

追问三:队列重复投递会怎样?

  • 考察点:至少一次语义。
  • 回答方向:worker 幂等消费,使用 job attempt、锁/租约、checkpoint 和外部副作用幂等。

推荐阅读

基于 MIT 协议开源