【问题标题】:Why does an Apache CXF 2.7.8 in WebLogic Application Server 12c client ignore FIN from the server?为什么 WebLogic Application Server 12c 客户端中的 Apache CXF 2.7.8 忽略来自服务器的 FIN?
【发布时间】:2014-09-22 21:03:00
【问题描述】:

我有一个 Apache CXF 2.7.8 使用者调用另一个 SOAP Web 服务。

在我的开发环境(Tomcat 6.0、jdk1.7.0_51、Windows 7)中,一切正常。

但是;当我将代码部署到测试环境(WebLogic 12.1、jdk1.7.0_51、RHEL 6)时,我得到一个 javax.xml.ws.WebServiceException: Could not send Message 异常,这是由 java.net.SocketTimeoutException: Read time out after x millis 引起的。

开发和测试实例调用完全相同的服务器。

当我执行网络跟踪时,我看到 CXF 使用同一个套接字连接发送许多请求(感谢 HTTP Keep-Alive)。最终,服务器发送FIN 指示客户端应停止使用此连接(并在需要时建立一个新连接)。客户端确认FIN,然后继续在同一个套接字上发送下一个请求,尽管已被告知断开连接(并确认该指令)。然后服务器发送一个RST(如预期的那样),告诉客户端离开。然后客户端再次尝试。最终,经过足够的时间,我们达到了读取超时,并抛出了上面的 SocketTimeoutException。

(顺便说一句:在windows开发平台上,客户端尊重FIN并为下一个请求建立一个新的套接字连接)。

当我禁用 HTTP Keep-Alive 时(使用指令here),服务器在客户端仅发送一个请求后发送FIN(正如它应该发送的那样)。客户端仍然使用该帧的ACK 来确认FIN,然后大胆地继续尝试使用该套接字。

我希望 HTTP Keep-Alive 能够正常工作,但我会接受没有它的情况。

是否有任何推荐的解决方案或故障排除的后续步骤?

【问题讨论】:

  • 软件不能忽略 FIN 并继续通过同一个套接字进行传输。这一定是平台错误,否则您的观察结果有误。
  • 原来它(在我看来)是一个平台错误(WebLogic 在使用它们之前未能检查以确保池套接字连接仍然有效)。在下面的答案中修复(让 WebLogic 进行检查)。

标签: java web-services http weblogic cxf


【解决方案1】:

tldr;将 -Dhttp.keepalivecache.sockethealthchecktimeout=10 添加到 WebLogic 服务器的 JVM 参数中。

这是我们最终学到的:

客户端(WebLogic 12c 上的 Apache 2.7.8)正在向服务器(不是 WebLogic 服务器)发送 SOAP HTTP 请求。

服务器(至少在某些情况下)未能在响应中发送“连接”标头。这导致 WebLogic 不知道它是否可以重用连接。当它尝试重用已被服务器关闭的连接时,我们得到了错误。

WebLogic 有一个参数可以指示它在重用之前对重用的连接执行健康检查,如果健康检查失败,则将其从池中逐出。将系统属性 'http.keepalivecache.sockethealthchecktimeout' 设置为非常低的值(比如 10,持续 10 毫秒)可以解决问题。

【讨论】:

    【解决方案2】:

    以下是我们目前所学到的,希望对其他人有所帮助:

    1. 在 Oracle JRE 1.7.0_51-b13 中,当用户 java.net.HttpURLConnection 和 javax.net.ssl.HttpsURLConnection(都是 java.net.URLConnection 的子类)启用 HTTP KeepAlive 时,服务器终止HTTP 连接(根据 RFC 允许这样做),JRE 不恰当地继续使用断开连接的套接字(当该套接字似乎处于 FIN_WAIT 状态之一时)。这样做时,JRE 在套接字发送上“等待”(永远不会返回响应),直到发生读取超时,此时抛出套接字超时异常。此功能在 WebSphere 下的 IBM JRE 中正常工作,但在 WebLogic 下的 Oracle JRE 中不能正常工作。

    2. 在同一 Oracle JRE 版本中,根据 RFC,当 HTTP 或 HTTPS 请求上的“Connection:”标头字段设置为“close”(而不是 Keep-Alive)时,URLConnection 的子类将继续尝试重用相同的底层套接字,即使他们不应该这样做。

    我们的解决方法是将“http.keepAlive”系统属性设置为“false”,以禁用所有连接上的保持活动状态。这不是一个可接受的长期解决方法,因为在每个请求上设置和断开连接所需的额外时间和资源开销是不可接受的 - 我们必须继续努力以使其正常工作。

    【讨论】:

    • 您好,请问有关于这个问题的后续吗?
    • 您确定问题出在 JRE 实现中吗?在 WebLogic 下,HTTP 堆栈被覆盖以使用自定义 WebLogic HTTP 堆栈(包 weblogic.net.http.*)...这听起来类似于 JIRA 问题 CXF-4524。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    相关资源
    最近更新 更多