0

ServletOutputStream.isReady()javadoc 说以下内容

返回:如果写入此 ServletOutputStream 将成功,则返回 true,否则返回 false。

尽管 Jetty 的ServletOutputStream实现,在流处于状态HttpOutput的情况下似乎表现得相当混乱。CLOSED它返回true

case CLOSED:
    return true;

来源:HttpOutput.java :1011 。

此外,当它是时,所有三种write方法都会HttpOutput抛出:EofExceptionCLOSED

case CLOSED:
    throw new EofException("Closed");

所以看起来 write 永远不会成功。这种行为背后的原因是什么?

4

1 回答 1

1

关键事实:close call 意味着写入操作。

CLOSED 内部状态表明流/输出的使用对于该调度是关闭的(而不是流本身实际上是关闭的)。

我们是如何进入这种状态的?某些事情触发了ServletOutputStream.close()(反过来HttpOutput.close()),现在不允许从当前调度对该流进行更多的写入。

在 CLOSED 状态下,会发生刷新。

  • 刷新将提交响应
  • 刷新将完成写入交换/连接/输出的各个层上存在的各种缓冲区。
  • 如果有一个聚合缓冲区(对于许多小写入),它会将其写出。
  • 如果有压缩层(gzip),它也会从那里强制刷新。
  • 然后所有这些缓冲区也通过Transfer-Encoding层(例如:分块)。
  • 然后发生网络写入。

HttpOutput也是所有嵌套请求的一个输出点,比如 using from include()whichRequestDispatcherHttpOutput在 the 期间重新打开供使用include(),然后再次关闭。

一旦HttpOutput完全和完全刷新/完成(不再调度,不再写入等),则完成最终缓冲区刷新,完成传输编码,重置 HttpOutput,回收,并返回到 HttpConnection 以供使用下一次交流。

我们可以在代码库中更好地处理 javadoc,或者至少使用更有意义的常量和变量名。

打开https://github.com/eclipse/jetty.project/issues/2687

关于写的 Jetty EofException(不是 JVM EOFException)。

一旦ServletOutputStreamCLOSED 用于特定调度,进一步调用write()将导致 Jetty EofException

还有一种EofException你的承诺响应细节被违反的地方。

例如:您声明了一个Content-Length40MB 的响应,但写入了 41MB,您超出了该提交响应的能力,这是一个 IOException。Servlet 规范告诉我们IOException在这种情况下抛出一个。

Jetty 将抛出 Jetty 内部EofException(扩展 IOException)以指示此特定场景并中止连接,从而破坏您可能想要的任何连接持久性。

于 2018-06-29T13:29:41.260 回答