我有一个由Tomcat提供服务的Java/JSP web应用程序,它使web服务调用到合作伙伴web服务以检索数据。合作伙伴服务中使用的技术未知。合作伙伴web服务经常出现长期中断,返回SocketTimeoutException:
java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.<init>(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.New(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
如果合作伙伴web服务出现短暂中断,然后很快恢复,我的应用程序可以很好地处理所有事情。
如果合作伙伴web服务的停机时间延长了一个多小时,而我的应用程序已经有数百次对该服务的调用全部超时,那么在某个时候,我的应用软件将达到无法恢复的状态。合作伙伴服务返回,但我的应用程序对该服务的调用仍然会导致相同的SocketTimeoutException错误。
如果我在那个时候启动并停止Tomcat,那么之后一切都会正常工作。
我没有使用http保持活跃。我的代码是关于清理所有对象实例的肛门,无论是否发生异常。TomcatJava进程似乎"用完"了一些资源(套接字?),每个错误都会丢弃一个,直到没有更多的资源可以使用为止。以前有人见过这种情况吗?有明显的解决方案吗?我对这件事做了很多搜索,没有发现任何人有同样的问题。
提前感谢!John
我过去遇到过这样的情况,即TCP_WAIT状态下的连接的TCP/IP堆栈中的插槽用完了,操作系统中有一些硬性限制,您可能会遇到这些限制。了解限制的方法是使用像netstat这样的工具。如果您在windows服务器上运行,您可以使用sysinternals中的一些工具。
你的问题的解决方案可能是一种叫做Circuit Braker的设计模式,这在书中有解释http://pragprog.com/book/mnee/release-it
使用断路器模式时,对远程web服务的调用会流经断路器,当对远程服务的调用过多失败时,断路器会打开断路器,而当断路器处于打开状态时,对远端服务的调用将立即在断路器代码中失败,通常您可以对断路器进行编程,以重试并查看它是否会再次打开。不管怎么说,这本书比我刚才给你的那本简短的书有更好的解释。
https://bitbucket.org/asaikali/circuitbreaker/有一个CircuitBreaker模式的开源示例实现。