5

Young Yang有一篇优秀的文章解释了如何使用 wsimport 创建具有异步 Web 服务调用的 Web 服务客户端工件。异步要求 WSDL 具有标记

<enableAsyncMapping>true</enableAsyncMapping>

在其绑定部分。如果您对带有 JAX-WS 注释的 Java 类使用自下而上的方法,则不能直接在 WSDL 中执行此操作,因为 WSDL 是 Web 服务器上生成的工件。相反,当在 WSDL 上执行 wsimport 时,您可以使用 Ant 或 Maven 等构建工具来包含此绑定。

生成的客户端工件具有异步方法调用,这些方法调用返回

Future<?>

或一个

Response

这是一个未来。

阅读 Yang 的文章后,我的问题是为什么不使用 Executors 和 Futures 来滚动我自己的异步 Web 服务调用。wsimport 创建的工件是否提供了一些我无法通过自己滚动的方法看到的优势?

如果有人对这两种方法都有经验或见解,我将不胜感激您的反馈。

4

2 回答 2

12

理论上,生成的异步客户端不需要阻塞线程。通过传递 AsyncHandler,系统可以在 Web 服务调用完成时使用 NIO 注册事件,并且可以调用该处理程序。根本没有线程需要阻塞。

如果你把你的同步Web 服务调用放到一个 executor 中,它仍然会阻塞一个线程直到结果到达,尽管至少这个阻塞仅限于 executor 中的线程池。

一旦您有数百个线程浮动,您的系统性能就会由于上下文切换而降低。

底层的 Web 服务库是否真的使用 NIO 是另一回事。JAX-WS 规范似乎不需要它。使用 JDK 1.6 并设置断点服务器端,我设置 100 个客户端关闭以调用服务器。我使用 JVisualVM 连接到客户端,可以看到它在每次调用服务器时创建了一个新线程。垃圾!

在网上环顾四周,我发现 Apache CXF 支持限制异步调用中使用的线程池。果然,使用由 CXF 生成的客户端并将正确的库放在此处讨论的类路径中,重新测试表明只使用了 25 个线程。

那么为什么要使用 jax-ws API 而不是自己构建呢?因为建立自己的需要更多的工作;-)

于 2012-10-01T21:37:28.757 回答
10

我知道它没有达到提示的问题,而只是补充了问题中包含的一个信息:

“相反,当在 WSDL 上执行 wsimport 时,您可以使用 Ant 或 Maven 等构建工具来包含此绑定。”

可以通过使用选项 -b 向 wsimport 添加自定义 xml 文件来生成异步客户端:

例子:

wsimport -p helloAsyncClient -keep http://localhost:8080/helloservice?wsdl -b customAsync.xml

customAsync.xml 内容:

<jaxws:bindings
        wsdlLocation="http://localhost:8080/helloservice?wsdl"
        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
        <jaxws:enableAsyncMapping>true</jaxws:enableAsyncMapping>
</jaxws:bindings>

这只是使用 ant 或 maven 生成异步客户端的另一种方法:)

于 2017-04-22T15:16:47.917 回答