0

我想通过 restify 服务器将上游 http.IncomingMessage 转发给客户端。这就是我到现在为止的想法。它提供转发能力。但是我认为这可能会导致内存泄漏:

var server = restify.createServer()

server.get('/test', function(req, res, next) {
    var upstreamReq = createUpstreamReq() // just creates a http.ClientRequest

    upstreamReq.on('response', function(upstreamRes) {
        if (upstreamRes.statusCode === 404) {
            // (1) I guess this leaks the upstreamRes body ?
            return next(new restify.errors.NotFoundError())
        }
        if (upstreamRes.statusCode !== 200) {
            // (2) is there a better way than pipeing the response to /dev/null?
            // I guess the advantage of this approach is that we can reuse the connection (not closed) ?
            upstreamRes.pipe(fs.createWriteStream('/dev/null'))
            return next(new restify.errors.InternalServerError())
        }
        res.setHeader('Content-Type', upstreamRes.header('Content-Type'))
        res.setHeader('Content-Length', upstreamRes.header('Content-Length'))
        upstreamRes.pipe(res)
        return next()
    })

    upstreamReq.end()
})
  • 我假设在上游的情况下,404此代码会泄漏upstreamRes主体(1),因为它从未被消耗(否pipe(somewhere))?
  • 一个不应该泄漏upstreamRes身体的明显解决方案(2)是将其通过管道输送到/dev/null. 这个问题有替代/更好的解决方案吗?
4

1 回答 1

0

似乎我跳过了文档中的一个重要部分http.ClientRequest

如果没有添加“响应”处理程序,则响应将被完全丢弃。但是,如果您添加一个“响应”事件处理程序,那么您必须使用来自响应对象的数据,方法是在有“可读”事件时调用 response.read(),或者添加一个“数据”处理程序,或者通过调用 .resume() 方法。在消耗数据之前,不会触发“结束”事件。此外,在读取数据之前,它将消耗内存,最终可能导致“进程内存不足”错误。

https://nodejs.org/api/http.html#http_class_http_clientrequest

所以正确的答案似乎是:

  • 您需要http.IncomingMessage为每个消耗响应 (a)http.ClientRequest
  • 如果您对返回的数据不感兴趣,推荐的方法是调用upstreamRes.resume(). 即使没有附加消费者,这也会启动数据流。
于 2016-06-08T11:03:26.430 回答