在 SOAP Web 服务调用上卡住线程
Stucked thread on SOAP webservice call
我在 Tomcat 容器中有一个线程卡住,我想找到原因来避免这个问题。
使用 jstack 我发现它在 SOAP 网络服务调用后卡住了:
pool-2-thread-1" #27 prio=5 os_prio=0 tid=0x00007fd2315ce800 nid=0x39 runnable [0x00007fd2415d2000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
- locked <0x0000000087eb10e0> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
- locked <0x0000000087eb1138> (a sun.net.www.protocol.http.HttpURLConnection)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
- locked <0x0000000087eb1138> (a sun.net.www.protocol.http.HttpURLConnection)
at java.net.URL.openStream(URL.java:1045)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:999)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:400)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:231)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:209)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:178)
at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:364)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:322)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:231)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:212)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:208)
at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:119)
at javax.xml.ws.Service.<init>(Service.java:77)
配置中缺少哪个超时?我正在使用标准选项。
您的客户端尝试从远程 URL 下载 SOAP 服务的 WDSL 文件。 HttpURLConnection
s 默认有一个无限 socket read timeout and an infinite connect timeout。在您的情况下,连接似乎在从服务器读取时卡住了。由于读取超时是无限的,您将永远卡住或至少直到连接被重置(例如通过路由器或
服务器)。
正如其中一条评论中已经提到的,可以通过系统属性 sun.net.client.defaultReadTimeout
和 sun.net.client.defaultConnectTimeout
配置默认超时(如记录 here). You could set these properties also at runtime, but you would have to do this before the properties are read. Unfortunately, the properties are read only once when the internal NetworkClient class 已加载。我还没有尝试过,但是在 class 加载之前,您不太可能能够在 Tomcat 容器中设置属性。如果您有机会更改Tomcat 的启动脚本,我强烈建议设置明确的超时(特别是在生产设置的情况下)。
设置显式超时通常是一个好方法。但是超时只能解决所描述的症状,而不能解决您的实际问题:您的 SOAP 客户端依赖于从远程位置成功下载 WSDL 文件。您可以从本地资源加载它,而不是从远程位置下载 WSDL 文件。有两种可能的方法可以做到这一点:
A) 如果您应该有权访问(生成的)客户端代码,您可以将 WSDL 位置的远程 URL 替换为 URL 您的 class 路径上的资源文件。有关示例,请参阅 。
B) 如果无法手动调整客户端代码,您可以使用目录文件,如文档所述 here.
我在 Tomcat 容器中有一个线程卡住,我想找到原因来避免这个问题。
使用 jstack 我发现它在 SOAP 网络服务调用后卡住了:
pool-2-thread-1" #27 prio=5 os_prio=0 tid=0x00007fd2315ce800 nid=0x39 runnable [0x00007fd2415d2000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
- locked <0x0000000087eb10e0> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
- locked <0x0000000087eb1138> (a sun.net.www.protocol.http.HttpURLConnection)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
- locked <0x0000000087eb1138> (a sun.net.www.protocol.http.HttpURLConnection)
at java.net.URL.openStream(URL.java:1045)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:999)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:400)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:231)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:209)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:178)
at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:364)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:322)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:231)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:212)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:208)
at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:119)
at javax.xml.ws.Service.<init>(Service.java:77)
配置中缺少哪个超时?我正在使用标准选项。
您的客户端尝试从远程 URL 下载 SOAP 服务的 WDSL 文件。 HttpURLConnection
s 默认有一个无限 socket read timeout and an infinite connect timeout。在您的情况下,连接似乎在从服务器读取时卡住了。由于读取超时是无限的,您将永远卡住或至少直到连接被重置(例如通过路由器或
服务器)。
正如其中一条评论中已经提到的,可以通过系统属性 sun.net.client.defaultReadTimeout
和 sun.net.client.defaultConnectTimeout
配置默认超时(如记录 here). You could set these properties also at runtime, but you would have to do this before the properties are read. Unfortunately, the properties are read only once when the internal NetworkClient class 已加载。我还没有尝试过,但是在 class 加载之前,您不太可能能够在 Tomcat 容器中设置属性。如果您有机会更改Tomcat 的启动脚本,我强烈建议设置明确的超时(特别是在生产设置的情况下)。
设置显式超时通常是一个好方法。但是超时只能解决所描述的症状,而不能解决您的实际问题:您的 SOAP 客户端依赖于从远程位置成功下载 WSDL 文件。您可以从本地资源加载它,而不是从远程位置下载 WSDL 文件。有两种可能的方法可以做到这一点:
A) 如果您应该有权访问(生成的)客户端代码,您可以将 WSDL 位置的远程 URL 替换为 URL 您的 class 路径上的资源文件。有关示例,请参阅
B) 如果无法手动调整客户端代码,您可以使用目录文件,如文档所述 here.