Как некоторые из вас могут знать, реализация ECF OSGi Remote Services поддерживает асинхронные прокси . Это позволяет потребителям удаленных сервисов легко использовать асинхронный / неблокирующий вызов для доступа к удаленному сервису. Например … вот простой интерфейс службы, который используется в нашем руководстве по удаленной службе :
public interface ITimeService { public Long getCurrentTime(); }
Как и в случае любой удаленной службы OSGi, любой потребитель, обнаруживший эту службу, потенциально заблокируется, когда он вызовет getCurrentTime (). Это просто природа семантики вызова / возврата, применяемой к удаленному взаимодействию … и так будет справедливо для любой реализации удаленных сервисов OSGi.
Подразделение ECF OSGi Remote Service предлагает асинхронные прокси, что означает, что если определен соответствующий интерфейс службы … например
public interface ITimeServiceAsync { public Future getCurrentTimeAsync(); }
тогда потребители смогут использовать ITimeServiceAsync для доступа к услуге … например:
ITimeServiceAsync tsa = ... get ITimeServiceAsync reference Future timeFuture = tsa.getCurrentTimeAsync(); ...do work... Long time = timeFuture.get();
В ECF 3.8.0 мы дополнительно добавили [3] … то есть возможность автоматически регистрировать ITimeServiceAsync в качестве службы на потребителе … так что (например) ссылка ITimeServiceAsync может быть введена через декларативные службы … например
...ds component impl... void bindTimeServiceAsync(ITimeServiceAsync tsa) { ...use or store tsa... }
Это [3] доступно в ECF 3.8.0. Обратите внимание, что сервисные интерфейсы не имеют абсолютно никакой ссылки ни на классы ECF, ни на классы OSGi. Ничего не нужно сейчас.
Как многие из вас наверняка знают … java8 только что вышел, и большая часть java8 — это улучшенная поддержка параллелизма, функционального программирования и лямбд. Эта поддержка параллелизма в java8 потенциально очень полезна для пользователей OSGi Remote Services.
Рассмотрим CompletableFuture, который, как следует из названия, является типом java.util.concurrent.Future. У него есть несколько очень хороших свойств для дизайнеров API / сервисов … главное в том, что совсем нет необходимости напрямую вызывать Future.get … но вы можете написать хороший, лаконичный и * гарантированно неблокирующий, но асинхронное * использование, такое как:
CompletableFuture cf = ...get CompletableFuture.... cf.thenAccept((time) -> System.out.println("time is: " + time));
Это хорошо … это совершенно не блокирует … и очень лаконично. Также вы можете делать очень интересные вещи с асинхронной / управляемой событиями цепочкой / фильтрацией и т. Д. И т. Д. Все гарантированно не блокируется … что является ключевой гарантией удаленного взаимодействия.
Вчера я понял, что с Java8 наши асинхронные прокси могут быть легко обобщены, чтобы сделать это:
public interface ITimeServiceAsync { public CompletableFuture getCurrentTimeAsync(); }
Я сделал несколько незначительных дополнений в реализации удаленного сервиса ECF для асинхронных прокси, и теперь это работает. Под этим я подразумеваю, что потребители произвольной удаленной службы теперь могут делать это
...service component impl...
void bindTimeServiceAsync(ITimeServiceAsync tsa) { // Get the CompletableFuture...no blocking here CompletableFuture cf = tsa.getCurrentTimeAsync(); // print out time when done...no blocking anywhere! cf.thenAccept((time) -> System.out.println("Remote time is: " + time)); }
Обратите внимание на несколько вещей:
- Там нет блокировки нигде. Это верно, хотя фактическое значение времени извлекается через удаленный сервис OSGi
- Хост удаленного сервиса не должен предоставлять какую-либо реализацию ITimeServiceAsync. Он построен RS ECL автоматически
- Очень легко справиться со сбоем (например, сбой сети / io) через CompletableFuture.handle. Это, очевидно, большая проблема для удаленных служб … которые гораздо более склонны к сбою из-за сети.
- Нет ссылки ни на классы OSGi, ни на классы ECF в коде хоста или потребителя.
Это хорошо для пользователей удаленных сервисов, потому что они не дают им надежных гарантий блокировки и могут быть очень эффективно реализованы (без дополнительных потоков) удаленными поставщиками услуг, использующими асинхронный обмен сообщениями (например, JMS и т. Д.). Это также позволяет им использовать все API-интерфейсы CompletableFuture (см. Javadoc CompletableFuture ).
Это, очевидно, будет частью ECF Luna … и я создал некоторый тестовый код (как выше), который я собираюсь использовать для создания другого учебника в следующем месяце. Посмотрите вики ECF для этого урока.
Единственный недостаток состоит в том, что это, конечно, зависит от Java8 … и поэтому требует, чтобы и удаленный хост-сервис, и потребитель использовали Java8, и чтобы поставщик распространения был немного расширен для использования CompletableFuture. К счастью, технически не сложно сделать эти улучшения, и мы сделаем классы поддержки доступными для тех, кто желает, чтобы Java8 улучшала существующего или своего собственного провайдера RS.
[1] https://wiki.eclipse.org/ECF/Asynchronous_Remote_Services
[2] https://wiki.eclipse.org/Tutorial:_Building_your_first_OSGi_Remote_Service
[3] https://bugs.eclipse.org/buug/sho_ ? ID = 420785