Асинхронные вызовы веб-сервисов с JAX-WS: Использовать поддержку wsimport для асинхронности или накатить свою собственную?

Янг Янг написал отличную статью, в которой объясняется, как использовать wsimport для создания артефактов клиента веб-службы, имеющих асинхронные вызовы веб-службы. Асинхронность требует, чтобы WSDL имел тег

<enableAsyncMapping>true</enableAsyncMapping>

в разделе привязок. Если вы используете восходящий подход с аннотированными классами Java JAX-WS, вы не можете сделать это непосредственно в WSDL, потому что WSDL является сгенерированным артефактом на веб-сервере. Вместо этого вы используете инструменты сборки, такие как Ant или Maven, чтобы включить эту привязку при выполнении wsimport в WSDL.

Сгенерированные клиентские артефакты имеют асинхронные вызовы методов, которые возвращают

Future<?>

или

Response

это будущее.

После прочтения статьи Янга мой вопрос заключается в том, почему бы просто не прокручивать собственные асинхронные вызовы веб-служб, используя Executors и Futures. Могут ли артефакты, созданные wsimport, дать какое-то преимущество, которое я не вижу по сравнению с подходом "покатай сам"?

Если у кого-то есть опыт или понимание обоих подходов, я буду признателен за ваши отзывы.

2 ответа

Решение

Теоретически, сгенерированные асинхронные клиенты не должны блокировать потоки. Передав AsyncHandler, система может использовать NIO для регистрации события после завершения вызова веб-службы и может вызывать этот обработчик. Нет необходимости блокировать потоки.

Если вы поместите синхронный вызов веб-службы в исполнителя, он все равно будет блокировать поток до тех пор, пока не будет получен результат, хотя по крайней мере эта блокировка ограничена пулом потоков в исполнителе.

Как только у вас появятся сотни потоков, производительность вашей системы будет ухудшаться из-за переключения контекста.

Вопрос о том, использует ли библиотека веб-служб NIO на самом деле, - это другой вопрос. По-видимому, это не требуется согласно спецификации JAX-WS. Используя JDK 1.6 и устанавливая серверную точку останова, я отключил 100 клиентов для вызова сервера. Используя JVisualVM, я подключился к клиенту и увидел, что он создал один новый поток за один вызов к серверу. Мусор!

Оглядываясь в Интернете, я обнаружил, что Apache CXF поддерживает ограничение пула потоков, используемых в асинхронных вызовах. Конечно, с помощью клиента, сгенерированного с помощью CXF, и размещения правильных библиотек в пути к классам, как обсуждалось здесь, повторное тестирование показало, что используются только 25 потоков.

Так зачем использовать jax-ws API, а не создавать свой собственный? Потому что создание собственного требует больше работы;-)

Я знаю, что это не достигает намеченного вопроса, но только дополняет одну информацию, включенную в вопрос:

"Вместо этого вы используете инструменты сборки, такие как Ant или Maven, чтобы включить эту привязку при выполнении wsimport на WSDL".

Асинхронный клиент можно сгенерировать, добавив пользовательский XML-файл, используя параметр -b для wsimport:

Пример:

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:)

Другие вопросы по тегам