使用 CXF 进行非阻塞 WS 调用

Posted

技术标签:

【中文标题】使用 CXF 进行非阻塞 WS 调用【英文标题】:Non-blocking WS call with CXF 【发布时间】:2014-08-11 11:01:57 【问题描述】:

我需要调用一个响应时间非常长(秒)的 WS - 在他们这边没有实现任何轮询/回调机制。

我认为最有效的方法是在收到响应时使用非阻塞 io 和某种回调机制。由于我们主要使用 Spring 和 CXF,我开始了一个概念验证项目来测试我的概念和配置本身。

幸运的是,有一个用于 cxf 的 HttpAsyncClient,并且有很好的教程如何配置它。但是在某些时候我卡住了:使用同步模式没问题,但是当我想使用回调时,它会抛出以下异常:

javax.xml.ws.WebServiceException: Could not find wsdl:binding operation info for web method getDataFromWebServiceAsync.
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:126)
    at com.sun.proxy.$Proxy46.getDataFromWebServiceAsync(Unknown Source)

ws接口:

@WebService
public interface SampleWebService 
    public Person getDataFromWebService(@WebParam String id);
    public Future<?> getDataFromWebServiceAsync(@WebParam String id, @WebParam(name = "asyncHandler", targetNamespace = "") AsyncHandler<Person> asyncHandler);

客户端测试(作为 TestNG 测试实现):

@Test(threadPoolSize = 5, invocationCount = 100)
public void testMultithreadedNonBlockingSampleWs()
        throws InterruptedException, ExecutionException 

    client.getDataFromWebServiceAsync("" + id.getAndIncrement(),
            new AsyncHandler<Person>() 
                @Override
                public void handleResponse(Response<Person> resp) 
                    Person person;
                    try 
                        person = resp.get();
                        log.info(person.getName() + " | " + person.getAge()
                                + " | " + person.getDescription());
                        Assert.assertNotNull(person);
                        Assert.assertNotNull(person.getName());
                     catch (InterruptedException | ExecutionException e) 
                        log.error("EXCEPTION WHILE PROCESSING RESPONSE CALLBACK");
                        e.printStackTrace();
                    
                
            );

服务器端spring配置:

<jaxws:endpoint id="sampleService"
    implementor="my.sample.SampleWebServiceImpl" address="/SampleWebService" />

客户端spring配置:

<jaxws:client id="client"
    serviceClass="my.sample.SampleWebService"
    address="http://localhost:8080/sample-ws-cxf/SampleWebService">
    <jaxws:properties>
        <entry key="javax.xml.ws.client.connectionTimeout" value="10" />
        <entry key="javax.xml.ws.client.receiveTimeout" value="11000" />
        <entry key="org.apache.cxf.transport.http.async.usePolicy" value="ALWAYS" />
        <entry key="org.apache.cxf.transport.http.async.ioThreadCount" value="2" /> 
    </jaxws:properties>
</jaxws:client>

从文章中我发现不清楚这种(非阻塞回调)是否真的可行,或者只有轮询/回调机制才能工作。只有这篇文章指出: http://czechscala.wordpress.com/2013/05/13/non-blocking-soap-web-services-invocation/

现在有人可以澄清一下吗? 有什么方法可以做到这一点? 或者以合理的方式处理长时间运行的 WS 调用的任何解决方案?

【问题讨论】:

我将“getDataFromWebServiceAsync”重命名为“getDataFromWebService_Async”,但没有任何改变。是否会导致我使用 java2wsdl 并且不知道如何在 Java 端反映“enableAsyncMapping”的问题?但我不应该需要它,因为正如我之前所说,在服务器端没有实现轮询/回调:我需要在客户端有一个简单的非阻塞解决方案。 我刚刚发现了这个非常相似的未解决问题:***.com/questions/5910660/…。我正在使用 cxf 3.0.1,以及带有 spring 3.2.2.RELEASE 的 httpasyncclient 版本 4.0.1。 如果我称之为同步方式,没有错误,它说它使用 AsyncHTTPConduit: log.info("*** Conduit: "+ClientProxy.getClient(client).getConduit( ).getClass().getName());但我需要用回调来调用它。以同步方式调用非阻塞 IO 没有任何好处。提示? 【参考方案1】:

如果我使用 '-asyncMethods' 参数从 wsdl 生成接口,一切都很好! 主要区别在于它会围绕我的 Person 对象生成一个名为 GetDataFromWebServiceResponse 的包装器对象。现在一切正常:通过普通接口调用服务器(未实现轮询/回调),但在客户端响应时调用回调方法。

工作 pom.xml 粒子:

<execution>
    <id>generate-sources</id>
    <phase>generate-sources</phase>
    <configuration>
        <sourceRoot>$full.path.to.generate.classes</sourceRoot>
        <wsdlOptions>
            <wsdlOption>
                <wsdl>$full.path.to.wsdl</wsdl>
                <extraargs>
                    <extraarg>-p</extraarg>
                    <extraarg>$package.name</extraarg>
                    <extraarg>-asyncMethods</extraarg>
                </extraargs>
            </wsdlOption>
        </wsdlOptions>
    </configuration>
</execution>

我建议使用 2.7 以上的 cxf。

现在我想知道如何有人可以强制从客户端调用轮询/回调样式的服务方法......但这将是另一回事:-)

【讨论】:

以上是关于使用 CXF 进行非阻塞 WS 调用的主要内容,如果未能解决你的问题,请参考以下文章

ArrayBlockingQueue使用

nginx异步非阻塞理解

[概念] 同步 异步 阻塞 非阻塞

阻塞非阻塞,同步异步总结

具有非阻塞 tcp 调用的 TThread

阻塞-非阻塞 VS 同步-异步