Асинхронные вызовы веб-сервисов с 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:)