首页 > 解决方案 > 正确处理长时间运行的请求中的 HTTP 连接生命周期

问题描述

我在使用端点时启动了一个繁重的 I/O 进程。该端点应立即响应客户端该进程已启动。

繁重的 I/O 任务可能需要长达 30 分钟,所以我想知道的是服务器和客户端之间的连接在什么状态下离开res.json(...)?套接字连接是否仍然打开/半打开?在这种情况下,我应该在之后手动销毁套接字res.json(...)吗?29heavyIO分钟后任务失败并转到快速错误处理程序是否可以?最后;这种模式是否不正确,例如,我应该以完全不同的方式处理 I/O 任务吗?

下面是一个最小的例子:

import express from 'express'

const app = express()

const asyncHandler = (handler) =>
  (req, res, next) => Promise.resolve(handler(req, res, next)).catch(next)
const heavyIO = () =>
  new Promise((resolve, reject) => setTimeout(() => Math.random() > 0.5 ? resolve() : reject('FAILED'), 1000))

app.get('/start', asyncHandler(async (_req, res) => {
  // I want to be able to initiate the process and send back
  // confirmation that the process has been started. I want the
  // client to be able forget about this request.
  res.json('ok...started process')

  // Then we start to run the heavy IO process. Without the "await" this could
  // lead to unhandled promise rejection.

  // If this fails, the rejected promise will flow to express default
  // error handling which is I think "finalhandler" by default.
  // Because the headers as sent (res.headersSent === true) the error
  // handler will log the error and destroy the socket connection.

  // If this succeeds, the server will probably close the socket connection as well
  // internally.

  // Up until this point the socket has been open (or half-open?) so is this a problem?
  
  // Does it mean that the client has been "up-keeping" this socket connection
  // somehow or has/can it have been timed out before this succeeds or fails.
  await heavyIO()
  console.log(`FINISHED I/O at ${new Date().toISOString()}! Exiting handler...`)
}))

app.listen(8080)

标签: javascriptnode.jsexpresssocketsasynchronous

解决方案


推荐阅读