"Error: Writing to server" - Occuring only on ubuntu

"Error: Writing to server" - Occuring only on ubuntu

我正在使用一个实现自定义功能的 jar 文件,该文件使用 jersey 作为 REST 客户端(版本 2.22.1)。虽然对于几次调用一切似乎都正常,但对于特定的 HTTP 调用,我得到了 "Error: Writing to server"、,但仅当 运行 in ubuntu 时。

在我的两台 ubuntu 开发 PC 上 运行 进行单元测试时发生错误。我的开发 PC 都是 Ubuntu 16.04 和 Oracle JDK:

~$ java -version
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)

$ java -version
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)

运行 来自 windows 机器的相同测试,没有给我任何错误。在我的 windows 机器上:

java -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)

完整错误的堆栈跟踪是:

javax.ws.rs.ProcessingException: java.io.IOException: Error writing to server at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:287) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:255) at org.glassfish.jersey.client.JerseyInvocation.call(JerseyInvocation.java:684) at org.glassfish.jersey.client.JerseyInvocation.call(JerseyInvocation.java:681) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681) at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437) at org.glassfish.jersey.client.JerseyInvocation$Builder.put(JerseyInvocation.java:326)

....

Caused by: java.io.IOException: Error writing to server at sun.net.www.protocol.http.HttpURLConnection.writeRequests(HttpURLConnection.java:666) at sun.net.www.protocol.http.HttpURLConnection.writeRequests(HttpURLConnection.java:678) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1534) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:394) at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285)

... 40 more

我只能假设错误的两个原因:

  1. jvm版本的区别
  2. 两个操作系统的网络设置不同

此错误出现在具有大量 http 负载的特定请求中。许多 post 的同事都建议在大型 http 请求期间发生这种情况,但是我没有发现任何 post 建议解决方案或将其与 Ubuntu 具体相关。

有什么提示吗?

哪些网络参数会影响此类功能?我怎么能 change/adapt 他们呢?

是否需要特定的 jvm 配置?

解决方案是在 TCP 级别,而不是在 JVM 版本或配置上。我更改了我的 ubuntu 网络设置,错误消失了。我想,它只发生在大的 HTTP 请求中,因为 TCP windows 太小或者什么的。

我按照 http://www.slashroot.in/linux-network-tcp-performance-tuning-sysctl 文章中的说明进行了以下设置:

net.ipv4.tcp_window_scaling = 1
net.core.rmem_max = 16777216 
net.ipv4.tcp_rmem = 4096 137380 16777216 
net.ipv4.tcp_wmem = 4096      137380   16777216

请注意,错误发生在负载约为 90kbytes 的 HTTP 请求上。为了成功,我需要尝试分配给每个 TCP 连接 (137380) 的 window 的值。

另请注意,这可能会对您的网络产生其他我无法真正预见或解释的副作用。使用较大的 window 值进行测试会导致其他请求延迟,我无法解释。因此,增加 TCP windows 大小并不是万能的解决方案。