Совсем не давно возникла необходимость создать ассинхронный веб сервис. Я выяснил, что на самом деле асинхронность, это нечто чужеродное для веб сервисов. Поэтому, если хотите асинхронности придется по извращаться. Ниже я опишу решения, которые удалось раскопать.
1. Асинхронный клиент для синхронного сервиса.
Данный подход, заключается в эмуляции асинхронности на стороне клиента.
Реализация хорошо описана здесь http://www.ibm.com/developerworks/ru/library/wes-0804_sedov/
От себя добавлю, что необходимо, с помощью утилиты wsimport, создать обвертку из Java классов. Которую мы будем использовать в клиенте, для коммуникации с WS.
Вот так, можно сформировать обычную синхронную обвертку
wsimport -keep -verbose http://localhost:8080/AeroSpike?wsdl
Но нам нужны асинхронные методы. Для этого запускаем утилиту, с такими параметрами
wsimport -b binding.xml -keep -verbose http://localhost:8080/AsyncSpikeServiceImpl?wsdl
где binding.xml файл биндинга, следующего содержания
<bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="http://localhost:8080/AsyncSpikeServiceImpl?wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
<enableAsyncMapping>true</enableAsyncMapping>
</bindings>
</bindings>
В качестве wsdlLocation, может быть указан как URL, так и WSDL файл.
При этом, если у веб сервиса есть методы, помеченные аннотацией OneWay (т.е метод вызываемый в не блокирующем режиме), для таких методов асинхронные обвертки создаваться не будут.
Производительность
Сделал замеры производительности на клиенте. В синхронном режиме, на один запрос уходит 43 ms. В асинхронном (с обратным вызовом AsyncHandler) 84 ms.
2. Дуплексный подход. Клиент - он же сервис обратного вызова.
Веб сервису приходит запрос, в заголовке которого содержится адрес, на который нужно отослать ответ. Можно сейчас, а можно через неделю.
Одна беда, поддержка WS-Adressing есть не во всех контейнерах сервлетов, и существуют трудности с генерацией правильной обвертки. Как это сделать в Jetty, я так и не нашел.
Суть вопроса, хорошо раскрыта здесь, применительно к Oracle SOA Suite:
http://samolisov.blogspot.com/2012/05/blog-post.html
и здесь, для WebSphere
http://www.ibm.com/developerworks/ru/library/ws-JAXsupport/
А это для WebLogic:
http://docs.oracle.com/cd/E17904_01/web.1111/e13734/asynch.htm
А здесь просто много теории
http://docs.oracle.com/cd/E17904_01/web.1111/e13734/asynch.htm
1. Асинхронный клиент для синхронного сервиса.
Данный подход, заключается в эмуляции асинхронности на стороне клиента.
Реализация хорошо описана здесь http://www.ibm.com/developerworks/ru/library/wes-0804_sedov/
От себя добавлю, что необходимо, с помощью утилиты wsimport, создать обвертку из Java классов. Которую мы будем использовать в клиенте, для коммуникации с WS.
Вот так, можно сформировать обычную синхронную обвертку
wsimport -keep -verbose http://localhost:8080/AeroSpike?wsdl
Но нам нужны асинхронные методы. Для этого запускаем утилиту, с такими параметрами
wsimport -b binding.xml -keep -verbose http://localhost:8080/AsyncSpikeServiceImpl?wsdl
где binding.xml файл биндинга, следующего содержания
<bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
wsdlLocation="http://localhost:8080/AsyncSpikeServiceImpl?wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
<bindings node="wsdl:definitions">
<enableAsyncMapping>true</enableAsyncMapping>
</bindings>
</bindings>
В качестве wsdlLocation, может быть указан как URL, так и WSDL файл.
При этом, если у веб сервиса есть методы, помеченные аннотацией OneWay (т.е метод вызываемый в не блокирующем режиме), для таких методов асинхронные обвертки создаваться не будут.
Производительность
Сделал замеры производительности на клиенте. В синхронном режиме, на один запрос уходит 43 ms. В асинхронном (с обратным вызовом AsyncHandler) 84 ms.
2. Дуплексный подход. Клиент - он же сервис обратного вызова.
Это самый правильный подход, базирующийся на спецификации WS-Addressing. С помощью него, можно организовать самую настоящую асинхронность. Выглядит это так:
Веб сервису приходит запрос, в заголовке которого содержится адрес, на который нужно отослать ответ. Можно сейчас, а можно через неделю.
Одна беда, поддержка WS-Adressing есть не во всех контейнерах сервлетов, и существуют трудности с генерацией правильной обвертки. Как это сделать в Jetty, я так и не нашел.
Суть вопроса, хорошо раскрыта здесь, применительно к Oracle SOA Suite:
http://samolisov.blogspot.com/2012/05/blog-post.html
и здесь, для WebSphere
http://www.ibm.com/developerworks/ru/library/ws-JAXsupport/
А это для WebLogic:
http://docs.oracle.com/cd/E17904_01/web.1111/e13734/asynch.htm
А здесь просто много теории
http://docs.oracle.com/cd/E17904_01/web.1111/e13734/asynch.htm
Комментариев нет:
Отправить комментарий