避免等待 Servlet 流实际上是一个受支持的案例???
我的Servler花了相当多的时间阅读和写作。从长远来看,这可能是一个问题,因为它阻塞线程只是为了每秒读取/写入几个字节。(*)request.getInputStream()
response.getOutputStream()
我对部分请求数据不感兴趣,在请求完全可用之前,处理不应开始。响应也是如此。
我想,异步IO可以解决这个问题,但我想知道什么是正确的方法。也许一个 servlet 在收集了整个输入后,用一个包装的、使用和调用链式的 servlet 替换了 ?Filter
ServletInputStream
ByteArrayInputStream
request.startAsync
- 有没有这样的过滤器?
- 我应该写一个还是应该使用不同的方法?
请注意,我的意思是避免在慢速 servlet 流上浪费线程。这与避免浪费线程只是等待某些事件是不一样的。startAsync
是的,目前这将是一个过早的优化。
我的读取循环,如请求
在我目前的输入流读取方法中没有什么有趣的,但在这里你是:
private byte[] getInputBytes() throws IOException {
ServletInputStream inputStream = request.getInputStream();
final int len = request.getContentLength();
if (len >= 0) {
final byte[] result = new byte[len];
ByteStreams.readFully(inputStream, result);
return result;
} else {
return ByteStreams.toByteArray(inputStream);
}
}
仅此而已,当数据不可用时,它会阻止; 来自番石榴。ByteStreams
我迄今为止的理解总结
正如答案清楚地表明的那样,使用servlet流而不浪费线程是不可能的。Servlet架构和通用实现都没有公开任何允许说“缓冲整个数据,只有在你收集了所有内容时才打电话给我”的东西,尽管他们使用NIO并且可以做到这一点。
原因可能是通常使用像nginx这样的反向代理,这可以做到这一点。nginx默认进行这种缓冲,直到两年前它才被关闭。
实际上是一个受支持的案例???
鉴于许多否定的答案,我不确定,但看起来我的目标
以避免在慢速 servlet 流上浪费线程
实际上是完全支持的:从3.1开始,有ServletInputStream.html#setReadListener,它似乎正是为此而生的。分配给处理最初调用的线程附加侦听器,并通过简单地从 返回返回到池。侦听器实现 ,当可以读取而不阻塞时调用,添加一段数据并返回。在 中,我可以对收集的数据进行整个处理。Servlet#Service
request.startAsync()
service
onDataAvailable()
onAllDataRead()
有一个例子,如何使用Jetty来完成它。它似乎也涵盖了非阻塞输出。
(*)在日志文件中,我可以看到请求花费长达八秒的时间,这些请求花费在读取输入(100字节标头+ 100字节数据)上。这种情况很少见,但它们确实会发生,尽管服务器大部分处于空闲状态。所以我想,这是一个非常糟糕的连接上的移动客户端(我们的一些用户从连接性如此差的地方连接)。