CXF,Camel和Spring线程阻塞问题

时间:2014-09-18 14:35:38

标签: java multithreading spring cxf apache-camel

问题在于Camel和CXF(端点和客户端)以及一次触发多个请求。

这是我们获得的例外情况:

java.net.SocketException: Unexpected end of file from server
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:772)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1323)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
    at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.getResponseCode(URLConnectionHTTPConduit.java:266)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1543)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1513)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1318)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:632)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:570)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:479)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:135)

我尝试使用SoapUI负载测试直接命中端点,但无法重现问题。它只发生在spring jaxws:client bean。

来自客户端的一次一个请求工作正常,我们从未看到错误,只有当我们尝试执行多个时。

在线程等待时也执行了线程转储,所有请求(其中5个)如下所示:

http-listener-1(1)" daemon prio=5 tid=0x00007fa2843e8800 nid=0x9d07 in Object.wait() [0x000000018a266000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000001708b27e8> (a org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit$AsyncWrappedOutputStream)
    at org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit$AsyncWrappedOutputStream.getHttpResponse(AsyncHTTPConduit.java:562)
    - locked <0x00000001708b27e8> (a org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit$AsyncWrappedOutputStream)
    at org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit$AsyncWrappedOutputStream.getResponseCode(AsyncHTTPConduit.java:674)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1543)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1513)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1318)
    at org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit$AsyncWrappedOutputStream.close(AsyncHTTPConduit.java:383)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:632)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
    - locked <0x00000001704175f8> (a org.apache.cxf.phase.PhaseInterceptorChain)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:570)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:479)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:135)

我也尝试过使用ASync客户端,而堆栈跟踪和线程转储看起来不一样,结果是一样的。

这似乎只发生在我们的开发实例(Mac笔记本电脑)上,我们使用JDK 1.7.x在我的Glassfish 4.0中运行(在我的机器上为1.7u65,在其他机器上略有不同版本)

其中一条骆驼路线,虽然它似乎会影响所有路线(并且它们设置相同)

from("cxf:/structure?serviceClass=" + StructureEndpoint.class.getName() + "&loggingFeatureEnabled=true")
            .routeId("structure")
            .to("log:com.test.camel")
            .recipientList(simple("direct:structure:${header.operationName}"));

当发生这种情况时,我从未看到loggingFeatureEnabled启用了camel / cxf日志输出,因此我们也看不到.to(&#34; log:*&#34;)输出。它永远不会到达这里。

可再现性测试:

SoapUI,简单的负载测试。 5点开始/结束线程 开始测试,获得前5个请求的错误。 测试通过我们的前端,它使用cxf客户端来命中后端camel / cxf服务。

直接点击camel / cxf服务不会导致任何问题。

Envirnoment测试更新

我们在Linux上运行了2个其他环境,两者都在JDK 1.7.0u60上,相同版本的glassfish没有出现这种行为。受影响的所有计算机仅限OS X. (将很快测试一个Windows框)

1 个答案:

答案 0 :(得分:0)

在对我能够测试的较小样本进行一些隔离和测试后,发现了问题。

使用较小的应用程序进行测试我可以部署在本地执行不同的服务器,一切正常。即使尝试将服务部署到Tomcat和Glassfish的前端,仍然没有问题。

一旦我将正面和背面放在同一台服务器上,如果我同时发送了5个请求,它就会卡住。我也尝试使用JAX-WS生成(而不是CXF)服务,但他们遇到了同样的问题,排除了CXF特定问题的问题。

根问题

Glassfish的默认http线程池最大值为5.因此,一旦我们尝试同时执行5个或更多请求.... blamo!从技术上讲,如果我们尝试了5个请求,那么我们确实会对资源执行10. 5,然后这些资源会自动执行5个后端。

解决方案

有几件事可以解决这个问题。增加glassfish中的线程池大小。 5反正似乎很小,所以无论如何都需要调整。

另一个是简单地将两个应用程序放在不同的服务器上,这将是如何配置生产,但可能会增加本地开发的开销。

杰出问题

唯一遗留未知的,是我们在linux qa / dev环境中看不到的原因。与他们不同的是他们坐在他们面前的阿帕奇,我们的本地实例没有。

相关问题