我使用Jetty作为服务器通过HTTP传输数据。数据来自消息队列,我以异步方式处理处理,在连接准备就绪时打印消息,并且有消息可用。当客户端断开连接时,我停止从队列中消费消息并清理专用于该流的所有资源。
Jetty选择发送响应块并默认设置Transfer-Encoding: chunked
- 这就是我想要的,因为这是一个无休止的流,我显然无法设置Content-Length
标头。
但是,我还需要在响应中设置Connection: close
。服务器将在负载均衡器后面运行,该负载均衡器将尝试与后端服务器保持持久连接,除非他们明确发送Connection: close
。我没办法配置负载均衡器,它完全不在我手中。如果负载均衡器保持连接打开,我无法知道何时停止从消息队列中消耗,因为连接将保持打开状态。
问题在于,当我执行response.setHeader("Connection", "close")
时,Jetty会停止将响应呈现为分块。它也没有设置Content-Length
标头,只是将输出流式传输到连接。据我所知,这在HTTP中并不合适,即使许多客户端可能会处理它。我真的想使用分块传输编码,并禁用keep-alive。我怎么能说服Jetty呢?
这是一个显示我的工作的最小例子。如果我删除设置Connection
标题的行Jetty块响应,但是它没有。
public class StreamingServer {
public static void main(String[] args) throws Exception {
Server server = new Server(2000);
server.setHandler(new AbstractHandler() {
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setBufferSize(1024);
// if I remove this line I get Transfer-Encoding: chunked
response.setHeader("Connection", "close");
response.flushBuffer();
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0);
final ServletOutputStream out = response.getOutputStream();
// start consuming messages from the message queue here
out.setWriteListener(new WriteListener() {
public void onError(Throwable t) {
// stop consuming messages and clean up resources
}
public void onWritePossible() throws IOException {
while (out.isReady()) {
// send the next available message from the queue
out.print(...);
}
}
});
}
});
server.start();
server.join();
}
}