В этой статье обсуждается способ использования декларативных сервисов OSGI для реализации защищенного брокера. Я часто хочу защитить свои декларативные сервисы, чтобы эти сервисы были недоступны для какого-либо пакета, и пока я работал над этим, я понял, что у меня были другие проблемы с DS, которые я решил решить также. В результате появился защищенный брокер, который является посредником между серверами и клиентами, который занимает 30 или более килобайт, и значительно сократил время разработки DS в моих проектах. Например, пример программного обеспечения реализует следующую ситуацию:
Рисунок 1: Справочное приложение
Сервер отправляет сообщение клиенту и заявителю , которые все присутствуют в защищенном домене или сборке . Заявитель также является частью второго собрания и направляет петицию поставщику , который отвечает предоставлением услуги (сообщением). Четыре элемента распределены по трем пакетам (клиент и поставщик были объединены в один пакет для демонстрационных целей). У меня все получилось менее чем за полчаса, и это включало в себя работу над инструментарием для этой статьи.
Вступление
Прежде чем начать, я хотел бы сказать, что я люблю декларативные услуги (DS)! Я работал с Eclipse / OSGI до появления DS, и с тех пор, как это стало обычным явлением, мне едва ли приходится иметь дело с загрузкой контактов, управлением зависимостями и всеми другими вещами, которые мешали разработке на основе компонентов.
Однако в реализации есть что-то, что заставляет меня запутаться (это мой недостаток, без сомнения), и мне потребовалось много времени, чтобы понять, что это было; сама идея того, что необходимо поместить «сервис» в сердце «клиента», не кажется очень интуитивной, хотя я могу понять логику реализации, но в своем уме я всегда вижу сервер «там» и клиентов быть где-то еще. С DS это так же, как если бы вы могли слушать свою любимую музыкальную станцию, потому что диджей в вашем подвале! В результате, каждый раз, когда я внедряю DS, я теряю много времени, борясь с чувством того, что нахожу интуитивным, и, поверьте мне, я делал это так часто, что я расстраиваюсь, что это все еще такая борьба!
Я ломал голову над этой проблемой, когда наткнулся на другую проблему, которая не связана с DS как таковой, но усугубляется вышеуказанной проблемой. В настоящее время я работаю над фреймворком с открытым исходным кодом, и я понял, что в этом случае я не хочу разрешать каким-либо пакетам доступ к услугам, которые я представляю через DS. Если, например, у меня есть плагин, который предлагает расположение папки в качестве службы, то я хочу быть уверен, что только доверенные пакеты могут получить к нему доступ.
Затем я начал мечтать о понятиях «клиенты», «серверы», «слушатели», «службы» и так далее. С помощью DS «сервис» (провайдер) в основном предоставляет один или несколько объектов, и «клиенты» (часто также косвенно «слушатели») могут получить доступ к этим объектам через специальный метод, обычно называемый notifySomething (..) . Интуитивно слушатель может быть «клиентом», а сервис — «сервером». Тем не менее, я часто оказываюсь под тем, что я называю петиционером . В этом случае служба (povider) пассивно ожидает, пока другой объект запросит все, что она может предложить, и не активно ее распространяет. Это, кстати, не как клиенты и серверы реализованы в веб-приложениях, хотя на первый взгляд вы так думаете. Действительно, клиент обращается к определенным ресурсам, отправляя запросы, но только после того, как сервер впервые предоставил веб-страницу для начала разговора (можно, конечно, указать, что клиент сначала должен зайти на веб-страницу, но затем я отвечу что пользователь действительно выполняет петицию, а не клиентское приложение). Я обнаружил, что шаблон petioner-provider обеспечивает дополнительный уровень безопасности для инфраструктуры, поскольку мошенническим пакетам придется активно выяснять, что предлагают поставщики, вместо того, чтобы провайдеры выкладывали все это для мошеннических пакетов для анализа.
Поэтому я экспериментировал с пакетом обертки вокруг DS, который затрагивает все темы выше, и для меня это действительно значительно упростило разработку. Пакет обертки реализует посредника и соответствует шаблону доски . Пакет составляет всего около 30 Кбайт, так что он вряд ли создает нагрузку на приложение. Я думал, что поделюсь этим с сообществом и, возможно, проведу некоторые дискуссии о том, как сделать вещи еще лучше.
Архитектура
Сначала я начал с архитектуры, изображенной на следующем рисунке.
Рисунок 2: Начальная архитектура
Идея заключалась в том, чтобы сервисы и клиенты могли регистрироваться у брокера, и у них должны были быть какие-то средства для согласования того, какие клиенты захотят подписаться на какой сервис. Эти два реестра гарантируют, что услуги не будут передаваться клиентам, а посредник будет передавать объекты между ними. После реализации этого я обнаружил, что DS стал намного более интуитивным, и дополнительным преимуществом было то, что я мог копировать и вставлять файлы component.xml и Component.Класс для каждого плагина, который необходим для предоставления или использования услуг. Однако затем начались кошмары, и постепенно мне пришло в голову, что я должен избавиться от всей идеи «клиентов», «серверов» и «услуг» на уровне реализации; на самом деле они были все одно и то же! Поэтому я изменил дизайн брокера следующим образом:
Рисунок 3: Переработанная архитектура
Эта альтернатива очень напоминает людей, встречающихся в общественном центре (вокруг дома). Участники могут зарегистрироваться (красные линии) и предоставить некоторую информацию о своих намерениях. Они могут хотеть быть аудиторией, или наоборот, они могут хотеть внести свой вклад. Раундхаус берет эту информацию и начинает сопоставлять участников, после чего они могут напрямую общаться друг с другом. Раундхаус также является объектом, который передается различным пакетам, которые хотят предоставлять или использовать услуги (или отправлять участников). Объект Match скрыт от глаз, поэтому Roundhouse также является щитом от внешнего мира.
В случае, если вам может быть интересно, какая польза от всего этого, я сначала покажу, что должен реализовывать типичный пакет. Конечно, нам нужно добавить компонент component.xml в папку OSGI-INF пакета:
<?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.mycompany.myapp.service"> <implementation class="org.mycompany.myapp.service.RoundhouseComponent"/> <reference bind="setAttendeeService" cardinality="1..1" interface="org.condast.osgi.IAttendeeService" name="IAttendeeService" policy="static" unbind="unsetAttendeeService"/> </scr:component>
Только имя и класс должны быть скорректированы для настройки для конкретного комплекта, остальные записи всегда одинаковы. Не забудьте включить в файл MANIFEST.MF следующее:
Service-Component: OSGI-INF/component.xml
ПРИМЕЧАНИЕ. Обратите внимание на предупреждающие сообщения в редакторе компонентов и в файле build.properties . Эти предупреждения обычно означают, что все будет работать неправильно. |
Объект RoundhouseComponent также довольно прост:
пакет org.mycompany.myapp.service import org.eclipselabls.osgi.ds.broker.service.AbstractAttendeeProviderComponent; открытый класс RoundhouseComponent extends AbstractAttendeeProviderComponent { @Override protected void initialise () { super .addAttendee (MyServerAttendee. getInstance ()); super .addAttendee (MyClientAttendee. getInstance ()); super .addAttendee (MyServiceAttendee. getInstance ()); … } } |
Как видите, все, что нужно, — это один компонент для добавления всех клиентов, сервисов и серверов, которые вам нужны! Я склонен реализовывать их как синглтоны, чтобы их можно было легко развернуть там, где (и когда) нужно в комплекте.
Каждый пакет, который хочет предоставить посетителям, должен реализовать эти три шага, что значительно упрощает использование декларативных сервисов.
Обеспечение безопасности участников
Пока что брокер позволяет посетителям входить в Круглый дом, но участники должны предоставить некоторые средства для определения того, с какими другими участниками они хотят соединиться. Ранее было упомянуто, что сборка участников-единомышленников регулируется объектом Match , а сопоставление регулируется объектом Palaver, который участники должны взять с собой. Объект Palaver (да, он основан на « Пиратах Карибского моря» ) может рассматриваться как приглашение посетить определенные собрания в Циркуляре и определяется следующим образом:
пакет org.eclipselabls.osgi.ds.broker.service; открытый интерфейс IPalaver <T extends Object> { / ** / ** / ** / ** |
Безопасность основана на трех проходной проверке. Поскольку я полагаю, что большинство разработчиков пакетов имеют добрые намерения, первый этап — это введение , которое представляет собой строку, которая должна быть одинаковой для всех участников сборки. С введением вы в основном определяете услугу, которая будет предлагаться (или запрашиваться). Таким образом, если для каждой службы, которую вы хотите предоставлять через DS, выбирается уникальное имя, например, на основе полного имени плагина, то другие службы не должны конфликтовать с вашим программным обеспечением. Первый участник, который войдет в здание круглого дома, станет председателем этого собрания, независимо от его функции, Если другой участник регистрируется с тем же введением, то начинается настоящая работа. Во- первых, новый участник должен предоставить маркер , который тестируется председателем, используя болтовня «s подтверждени метод. В простой (небезопасной) ситуации маркером может быть введение, которое проверяется на равенство. Если требуется защищенная связь, здесь могут быть реализованы более сложные схемы. Как правило, они должны быть реализованы на уровне, когда программное обеспечение становится проприетарным.
Последняя часть объекта Palaver определяет, хочет ли посетитель требовать полного внимания, что типично для сервера. Большая часть обмена данными между посетителями осуществляется в одноадресной или многоадресной рассылке (один сервер и ноль или более клиентов), и поэтому участник, который будет выступать в качестве сервера, обычно захочет требовать сборки. Это является возможным реализовать [n..m] связь между серверами и клиентами, но только один из участников в сборке могут претендовать на внимание ! В качестве примера, следующий посетитель предоставляет услугу .
пакет org.mycompany.myapp.service import org.eclipselabls.osgi.ds.broker.service.AbstractPalaver; приватный статический MyServiceProvider посетители: новый MyServiceProvider (); private MyServiceProvider () { класс Palaver расширяет AbstractPalaver <String> { protected Palaver () { super («my.application.service.A»); } @Override public String giveToken () { return scramble ( super .getIntroduction () ); } @Override public boolean verify (Object token) { return unscramble ( super .getIntroduction (), token); } } |
Приведенный выше фрагмент дает представление о возможном поставщике. Объект Palaver имеет доступ к определенным методам шифрования и расшифровки, которые защищают сборку. Сам провайдер довольно прост, так как вся тяжелая работа выполняется под капотом. Если провайдер становится частью сборки, он ожидает, пока метод onDataReceived () пройдет передачу сервиса. Обратите внимание, что AbstractPovider аннотирован тремя объектами, токеном, запросом и предоставляемым сервисом:
AbstractProvider<Token, ARequest, MyService>
Ниже приведен фрагмент другого пакета, в котором указан соответствующий заявитель .
пакет org.mycompany.my.other.app.service import org.eclipselabls.osgi.ds.broker.service .AbstractPalaver; import org.eclipselabls.osgi.ds.broker.service.AbstractProvider; открытый класс MyPetitioner расширяет AbstractPetitioner <String, ARequest, MyService> { частный статический MyPetitioner посетители = новый MyPetitioner (); private JxtaServiceContainerPetitioner () { super ( new Palaver ()); } публичная статическая JxtaServiceContainerPetitioner getInstance () { / ** protected Palaver () { @Override public String giveToken () { return scramble ( super .getIntroduction () ); } @Override public boolean verify (Object token) { return unscramble ( super .getIntroduction (), token); } } |
Как видите, заявитель практически идентичен поставщику, за исключением метода обращения (…), который запускает связь. Еще одно отличие заключается в том, что провайдер скрывает в качестве значенияappAttention значение true , а заявители — в false . Поэтому в ситуации по умолчанию ожидается один поставщик и ноль или более петиционеров.
Серверы, клиенты, слушатели, провайдеры и просители
Во введении было упомянуто, что весь вопрос о клиентах, серверах и тому, что не было бы решено на уровне реализации, и до сих пор мы в основном имели дело с посетителями, которые регистрируются в RoundHouse и собираются в сборках. Тем не менее, мы можем легко настроить участников для выполнения задач, описанных выше. Несколько сценариев изображены ниже:
инициатор |
ответчик |
мощность |
Описание |
Требовать внимания |
клиент |
сервер |
[M..1] |
Сервер предлагает услугу зарегистрированным клиентам |
сервер |
поставщик |
слушатель |
[M..n] |
Провайдер предлагает услуги зарегистрированным слушателям |
~ поставщик |
проситель |
поставщик |
[M..n] |
Заявитель запрашивает услугу, предлагаемую поставщиком |
~ поставщик |
В классической модели клиент-сервис клиент инициирует связь, запрашивая сервис, который затем предоставляет сервер. Шаблон наблюдателя, который часто используется в программировании, обычно следует сценарию провайдера-слушателя, где слушатель регистрируется для службы и получает уведомление, когда она становится доступной. В JAVA это часто следует за отношением [1..n] (с печально известными конструкциями addListener (..) и removeListener (.. )), но иногда диспетчеромможет быть помещен между ними для создания отношения [m..n]. Последний сценарий является одним из моих любимых, так как он в основном такой же, как и стандартная модель клиент-сервер, за исключением того, что несколько провайдеров могут быть подключены. Диспетчер в основном делает немного больше, чем просто передает информацию, но если он тоже реализует шаблон доски, диспетчер действительно повышен до брокера. Roundhouse предоставляет средства ведения переговоров запрошенных услуг, а не их пропускают через. Также возможно, что заявитель реагирует на предоставленную услугу путем отправки данных и т. Д., Что позволяет использовать довольно сложные формы общения.
В последних двух сценариях поставщик либо инициирует, либо отвечает на запрос. Однако, если используется только один поставщик — что является наиболее распространенной ситуацией — поставщик может требовать внимания.
Стало ясно, что, не делая каких-либо ссылок на предполагаемую функциональность на уровне реализации брокера, мы дали себе большую гибкость в настройке участников в соответствии с нашими потребностями.
Программное обеспечение
Реализация защищенного брокера была включена в следующий zip-файл (архив Eclipse), который включает в себя плагин для двоичных файлов и источников в папке lib и исходный код в папке src. Вы также можете использовать сайт обновлений . Исходный код также доступен как репозиторий git на Eclipselabs . Они распространяются в библиотеке с открытым исходным кодом Eclipse, что означает, что они могут свободно использовать и распространять. Если вы хотите использовать защищенного брокера в своих собственных проектах, все, что вам нужно, — это пакет org.eclipselabs.osgi.ds.broker . Также включен ряд тестовых плагинов (сервер, клиент и поставщик), которые могут служить базовой реализацией для различных сценариев, описанных выше.
Реализация также добавляет ряд команд в консоль OSGI:
- Roundhouse : список всех доступных команд
- участники : перечисляет всех участников, которые добавляются в Roundhouse .
- соответствует : перечисляет всех участников, которые формируют сборку
- Ожидание : список всех участников, которые еще не были сопоставлены.
Конфликты внимания регистрируются и всегда приводят к тому, что один или несколько участников находятся в состоянии ожидания. Если Palaver реализован правильно, то эти конфликты внимания будут основным источником проблем.
Вывод
Защищенный брокер предоставляет дополнительный уровень по сравнению с механизмом декларативных сервисов OSGI, который занимает очень мало места в памяти, делает DS легко конфигурируемым, применяет шаблон Whiteboard и обеспечивает уровень безопасности, который стоит учитывать, особенно когда кто-то работает над фреймворками. Я широко использую брокера и обнаружил, что он значительно упростил разработку и использование (защищенных) DS. Но дайте мне знать, что вы думаете, и я приветствую любые улучшения программного обеспечения!