Http 服务器 - Netty FileRegions 是否可重用?

Http Server - Are Netty FileRegions reusable?

我目前正在一个 HTTP 服务器上工作,有些事情表现得很奇怪。 我想生成动态内容,也只提供静态文件。 提供动态生成的内容没有问题。 因为我想从零拷贝中获利,所以我使用 FileRegions 来提供静态文件。 我的通道管道包含以下处理程序(按此顺序):

  1. HttpRequestDecoder
  2. HttpResponseEncoder
  3. HttpObjectAggregator
  4. ApiMapper

ApiMapper 是可共享的,派生自 SimpleInboundHandler。 创建时,ApiMapper 从静态文件创建一个 FileRegion。 现在每次请求“/”uri 时都会发生这种情况:

  1. DefaultHttpReponse 已写入 ChannelHandlerContext。 DefaultHttpReponse 未被重用,包含 headers for Content-Type 和 Content-Length
  2. FileRegion 的 ReferenceCount 使用其保留方法增加。 然后使用 FileRegion 作为参数在 ChannelHandlerContext 上调用 writeAndFlush。 向返回的 ChannelFuture 添加一个 ChannelFutureListener,它打印 "DONE".

第一个响应按预期工作,浏览器获取完整文件并正确显示并打印 "DONE"。 但是,如果再次调用“/”uri,浏览器不会显示任何内容,只会永远加载,但 "DONE" 会被打印出来。 然后在我重新启动服务器后,我使用 telnet 手动拨打电话。第一个响应是正确的,但后来我注意到第二个调用只有returns一个header,但没有内容。 "DONE" 仍然打印。

所以我的问题是:同一个 FileRegion object 可以多次使用吗?我做错了什么吗?

不,您不能以这种方式多次写入相同的 FileRegion,因为 transferred 状态已在 DefaultFileRegion 对象上更新。您需要为此处的每个写入创建一个新的 DefaultFileRegion 实例。

您还需要确保在 FileRegion 之后发送 LastHttpContent,否则 HttpResponseEncoder 中的状态机在您编写第二个 HttpResponse.