Java CXF、Camel和Spring线程阻塞问题

Java CXF、Camel和Spring线程阻塞问题,java,multithreading,spring,cxf,apache-camel,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) a

问题在于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:clientbean中

每次从客户机发出一个请求就可以正常工作,我们永远不会看到错误,只有当我们尝试执行多个请求时才会看到错误

在线程等待时还执行了线程转储,所有请求(其中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)
当这种情况发生时,我从未看到loggingFeatureEnabled启用的camel/cxf日志输出,因此我们也没有看到.to(“log:*)输出。它永远不会到这里

可复制测试: SoapUI,简单的负载测试。在5处开始/结束螺纹 开始测试,获取前5个请求的错误。 测试通过我们的前端进行,它使用cxf客户机访问后端camel/cxf服务

直接访问camel/cxf服务不会导致任何问题

环境测试更新
我们还有另外两个运行在Linux上的环境,都在JDK1.7.0u60上,与glassfish版本相同,没有表现出这种行为。所有受影响的机器仅限于OS X。(不久将测试一个windows机箱)

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

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

一旦我把前端和后端放在同一台服务器上,如果我同时向它发送5个请求,它就会卡住。我还尝试使用JAX-WS生成的(而不是CXF)服务,但它们也有同样的问题,排除了与CXF相关的问题

根本问题 Glassfish的默认http线程池最大值为5。所以,当我们试图同时做5个或更多的请求时……该死!从技术上讲,如果我们尝试了5个请求,我们实际上只做了10个。5到资源,然后它们将出去并对后端本身执行5

解决方案 有几件事可以解决这个问题。增加glassfish中的线程池大小。5看起来很小,所以不管怎样都需要调整

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

悬而未决的问题 唯一未知的是,为什么我们在linux qa/dev环境中看不到这一点。与之不同的是,它们前面有apache,而我们的本地实例没有

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