Шлюзы Интернета вещей обычно устанавливаются на устройствах, предназначенных для работы в течение более длительных периодов времени без простоя. Общим требованием к шлюзу является обеспечение непрерывной обработки сообщений, собранных из поля, даже когда изменения конфигурации должны быть применены к устройству. Хотя в мире Java технологию OSGi обычно отождествляют с функциями горячего повторного развертывания, я хотел бы рассказать вам больше о возможностях, которые Apache Camel, работающий вне среды OSGi, может привнести в эту тему.
Добавление новых компонентов во время выполнения
Apache Camel использует компоненты для предоставления соединителей, которые могут использоваться для получения сообщений от различных конечных точек (а также для отправки сообщений на конечные точки). Например, шлюз на базе Apache Camel может использовать компонент Paho MQTT для получения команд управления из центра обработки данных и в то же время использовать компонент Netty для связи с поддерживаемыми службами REST.
Теперь представьте, что в какой-то момент мы решили добавить компонент Salesforce к нашему шлюзу, чтобы копия сообщения, отправленного нами бэкэнд-службе REST, также могла быть отправлена непосредственно на нашу учетную запись Salesforce.
Можем ли мы как-то динамически добавить банку, содержащую компонент Salesforce, ко всем нашим устройствам производственных шлюзов, развернутым в полевых условиях? Поскольку шлюзы постоянно обрабатывают сообщения от датчиков, мы хотели бы избежать перезапусков устройств.
Динамические обновления с использованием конечных точек Camel Grape
Camel 2.16 поставляется с новым компонентом Grape на основе Groovy. Grape является частью языка Groovy — это библиотека, которая может загружать другие библиотеки и добавлять их в путь к классам текущей JVM. Компонент Grape загружает библиотеки jar из файловых репозиториев (включая репозитории Maven) и динамически добавляет эти jar в путь к классам приложения. Как только библиотека загружена, Camel может использовать новые компоненты и форматы данных, предоставляемые этими jar-файлами. Например, следующий маршрут Camel загрузит и установит компонент Camel Saleforce:
from("direct:start").
to("grape:org.apache.camel/camel-salesforce/2.15.2");
После того, как банка Saleforce была загружена, вы можете использовать его на маршрутах Camel. Все это без перезапуска приложения шлюза:
ProducerTemplate template = camelContext.createProducerTemplate();
template.sendBody("direct:dynamicEndpoint", "salesforce:createSObject");
...
from("direct:dynamicEndpoint").
recipientList().body();
Обновления по воздуху
Как мы можем динамически обновлять несколько шлюзов одновременно, используя беспроводную технологию? Поскольку шлюзы обычно работают в среде с ненадежным сетевым подключением, я рекомендую, чтобы шлюз прослушивал сообщения MQTT, отправленные из центра обработки данных. Клиент MQTT способен обрабатывать нестабильное сетевое соединение. Клиент MQTT, установленный на шлюзе, должен подключаться к данной теме «обновления» (давайте назовем ее «беспроводной» темой). Всякий раз , когда мы хотели бы загрузить компонент динамически мы можем просто использовать MQTT над сотовой темой и отправить координаты Maven артефакта мы хотим быть загружены на устройства. Для этой цели мы можем использовать компонент Camel Paho:
// This code is executed on the data center side.
ProducerTemplate template = camelContext.createProducerTemplate();
// Tell all our devices connected to the over-the-air MQTT topic
// to download Camel Salesforce connector.
template.sendBody("paho:over-the-air", "org.apache.camel/camel-salesforce/2.15.2");
Следующий маршрут Camel, развернутый на полевых устройствах шлюза, можно использовать для получения запросов на обновление от брокера MQTT и отправки их компоненту Grape:
from("paho:over-the-air").
to("grape:over-the-air");
Это все, что вам нужно для загрузки и загрузки новой библиотеки на все ваши шлюзы.
Работа с ошибками загрузки
Вам может быть интересно, что происходит, когда компонент Grape не может загрузить запрошенный артефакт, например, из-за проблем с сетью, которые часто встречаются в полевых условиях. Это тот момент, когда в Camel и его политику возврата обработчиков ошибок Camel включаются . Вы можете легко сказать Camel, какую стратегию повторных попыток следует использовать для получения и загрузки требуемой зависимости. Все, что вам нужно сделать, это использовать немного Camel DSL:
errorHandler(defaultErrorHandler().maximumRedeliveries(10).useExponentialBackOff());
Используя этот подход, вы можете быть уверены, что Camel будет продолжать пытаться загрузить запрошенную библиотеку. Обычно после определенного количества попыток загрузить артефакт вы хотите отправить MQTT-сообщение об ошибке обратно в центр обработки данных, чтобы ваша операционная группа могла получать уведомления о проблемах обновления на данном устройстве.
Загрузка патчей на шлюз перезагружается
Другой естественный вопрос — сохранятся ли патчи, загруженные компонентом Grape, после перезапуска шлюза. Да, компонент Camel Grape отслеживает загруженные исправления (по умолчанию список развернутых исправлений хранится в файловой системе устройства в виде простого текстового файла). Если вы хотите сообщить Camel о загрузке установленных исправлений, добавьте вызов метода GrapeEndpoint.loadPatches в определение вашего маршрута:
import static org.apache.camel.component.grape.GrapeEndpoint.loadPatches;
...
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
loadPatches(camelContext);
}
});
Список исправлений, установленных на шлюзе
Вас также может заинтересовать список исправлений, установленных на конкретном устройстве шлюза. Следующий маршрут демонстрирует, как соединить встроенный HTTP-сервер на базе Netty с компонентом Grape …
import static org.apache.camel.component.grape.GrapeEndpoint.loadPatches;
...
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
loadPatches(camelContext);
from("netty4-http:http://0.0.0.0:80/patches").
setHeader(GrapeConstants.GRAPE_COMMAND, GrapeCommand.listPatches).
to("grape:listPatches");
}
});
… чтобы вы могли открыть следующий URL в веб-браузере и просмотреть список установленных артефактов:
$ curl http://your.gateway.com/patches
org.apache.camel/camel-salesforce/2.15.2
org.apache.camel/camel-ftp/2.15.2
Резюме
Как видите, Camel в сочетании с возможностями загрузки классов Groovy предоставляет функции горячих обновлений, чрезвычайно полезные для систем IoT. Способность Camel предоставлять обновления во время выполнения по беспроводной сети является интересной альтернативой для развертываний OSGi. С компонентом Camel Grape вы можете воспользоваться динамической загрузкой классов, сохраняя при этом все преимущества плоского пути к классам.