среда, 3 октября 2012 г.

Java, Web Service и Асинхронность

      Совсем не давно возникла необходимость создать ассинхронный веб сервис. Я выяснил, что на самом деле асинхронность, это нечто чужеродное  для веб сервисов. Поэтому, если хотите асинхронности придется по извращаться. Ниже я опишу решения, которые удалось раскопать.

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. В асинхронном (с обратным вызовом AsyncHandler84 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











Комментариев нет:

Отправить комментарий