Apache Camel: ваш союзник с открытым исходным кодом для промежуточного программного обеспечения, ориентированного на сообщения

Если вы имеете дело с несколькими источниками и целевыми точками данных, стоит попробовать Apache Camel.

Сначала мы использовали и изучили Apache Camel для проекта развития банковской сферы. Хотя микросервисная архитектура не требовала интенсивной обработки данных (в большинстве случаев просто реорганизация, переименование и группировка), проблема заключалась в работе с несколькими источниками и местами назначения данных. Мы работали с кешем, двумя базами данных (реляционной и нереляционной), очередью сообщений и интеграцией нескольких внешних сервисов как с Rest, так и с SOAP.

Благодаря упрощению коммуникаций и написанного для него кода, четкости информационного потока и предоставления подключаемых модулей для каждой необходимой интеграции Camel лучше всего подходил для этой работы.

Apache Camel действительно хорошо работает в архитектурах, в значительной степени построенных на открытом исходном коде. Эта бесплатная платформа интеграции поддерживает более 50 форматов данных и содержит несколько сотен компонентов, которые используются для доступа к базам данных, очередям сообщений, API… вы называете это. Как фреймворк с открытым исходным кодом Camel полагается на поддержку своего сообщества. Имейте в виду, что это может потребовать обширных исследований и определенного уровня коллективных знаний, чтобы в полной мере воспользоваться его преимуществами.

Итак, приступим!

Этот пост дает вам всестороннее введение в Camel без каких-либо предварительных знаний. Понимание того, как он обрабатывает данные, поможет техническим руководителям и архитекторам решить, будет ли Camel хорошим выбором для их проекта и команды. Кроме того, это поможет новым разработчикам начать проект с Camel и понять, как он структурирует код и роль каждой части.

Анатомия приложения на основе верблюдов

Верблюжьи маршруты

Приложение Camel состоит из серии маршрутов, которые представляют собой объекты, которые можно настроить для перемещения информации от одной конечной точки к другой. Маршрут верблюда начинается с (конечная точка) и заканчивается до (конечная точка), и он перемещает блок информации от начальной конечной точки к конечной конечной точке с промежуточной обработкой, если это необходимо. Этими конечными точками могут быть другие верблюжьи маршруты, файлы, веб-сайты, очереди или кеши, что особенно интересно для простой интеграции нескольких видов транспортных методов в одну модель: HTTP, ActiveMQ, JMS, CXF и т. Д. .

Маршруты верблюда настраиваются в методе configure () RouteBuilder (org.apache.camel.builder.RouteBuilder). Все маршруты могут быть включены в один файл или, скорее, в несколько файлов по категориям для лучшей организации.

Позже мы рассмотрим это на примерах. Но сначала давайте поговорим о REST API с Camel.

REST API

Camel также предоставляет возможность создавать REST API с помощью определений маршрутов, подобных тем, которые мы изучали. Маршрут REST API начинается со слова rest и требует HTTP-метода, такого как get (), post (), put () и т. Д.

Ниже мы показываем пример Camel Route Builder с определением REST API:

Давайте разберем это определение маршрута шаг за шагом.

Прежде всего, класс расширяет RouteBuilder и переопределяет метод configure (), в котором мы определяем все необходимые маршруты и определения REST. Аннотация @Component необходима Spring для распознавания и сканирования класса.

Затем мы определили предложение restConfiguration (), которое позволяет нам настраивать определенные аспекты нашего REST API по мере необходимости.

Затем мы определили конечную точку GET с путем «/ hello». Как мы видим, для этой цели используются зарезервированные ключевые слова rest и get, указывающие путь к конечной точке. Мы также добавили логику внутрь определения, которому предшествовало ключевое слово route (). Эта логика выбирает между заголовком имени или значением по умолчанию «мир» в зависимости от того, присутствует ли заголовок. Эта структура эквивалентна структуре if-else, с которой мы все знакомы, являясь choice () первым предложением, when () условием и в противном случае ( ) значение по умолчанию для значений, которые не соответствуют вышеупомянутому условию. Может быть столько предложений when (), сколько требуется.

Внутри выбора мы используем значение заголовка запроса «имя» запроса, чтобы определить то, что мы называем свойствами. А пока давайте просто скажем, что свойства - это значения, которые, в отличие от заголовков, действуют на протяжении всего цикла работы приложения. Об этом мы поговорим позже.

Давайте посмотрим на эту конечную точку в действии:

Теперь давайте внесем несколько изменений, чтобы лучше понять, как работают маршруты.

Как мы видим, мы можем определить множество конечных точек с помощью одного и того же предложения rest (), и путь также может быть определен в определении каждой конечной точки вместе с ее методом.

Логика каждой конечной точки может содержаться в другом определении маршрута, чтобы упростить код. Мы используем компонент direct для определения синхронных маршрутов, которые могут быть вызваны другими маршрутами Camel в том же CamelContext. Другими примерами компонентов являются File, ActiveMQ, CXF, HTTP, Kafka, MongoDB и т. Д. Как мы упоминали ранее, поток информации, который проходит по маршрутам, определяется с помощью предложений from (конечная точка) и в (конечную точку).

Обработка исключений

Исключения можно перехватывать в маршрутизаторе с помощью предложения onException (). Допустим, мы, например, звоним во внешнюю службу, но она не отвечает вовремя. Мы, вероятно, захотим поймать TimeOutException и сделать что-то для правильного ответа, например, обработать информацию об ошибке определенным процессором и отформатировать ее в соответствии с нашими предпочтениями. То же самое касается любых исключений. Вернемся к примеру "hello world" и предположим, что параметр запроса name является обязательным:

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

Важно упомянуть предложение handled (), которое определяет, что делать при возникновении исключения. В этом случае, поскольку мы хотим остановить выполнение и обработать исключение, мы использовали handled (true). Если бы мы использовали handled (false), исключение было бы повторно сгенерировано, и его можно было либо перехватить в другом предложении onException, либо вызвать сбой приложения. Значение по умолчанию - false. Это означает, что если мы не добавим предложение, исключение продолжит вызывать сбой приложения.

Это произойдет, если вместо этого мы будем использовать .handled (false) (или none):

Биржи

Итак, что за структура проходит по этим маршрутам, о которых мы говорили? Это информационный блок, который мы называем биржей. Информация хранится в свойствах, заголовках и теле Exchange, некоторые из которых мы рассмотрели в предыдущих примерах.

Заголовки и тела изменчивы и сохраняются в двух разных сообщениях или частях обмена: IN (входящая информация) и OUT (исходящая информация). Мы называем их нестабильными, потому что они не действуют на протяжении всего цикла приложения, а скорее умирают после достижения конечной точки или обработки информации из обмена. С другой стороны, свойства являются постоянными, а это означает, что после их установки к ним можно получить доступ и изменить их во всем потоке.

Процессоры

Ранее мы упоминали, что информация, которая проходит по маршрутам Camel, может быть обработана. Что это значит? Например, нам может потребоваться установить определенные свойства в Exchange, проверить или преобразовать данные, обработать исключения и т. Д.

Обработка данных, о которой мы говорили, выполняется в классе Processor, который реализует интерфейс Camel Processor (org.apache.camel.Processor), который может выглядеть примерно так:

В приведенном выше примере мы видим, как установить заголовок в обмене, который впоследствии может быть доступен и использован в маршруте. В бирже также можно задать тело и свойства. Заголовки и тела устанавливаются аналогично, хотя свойства немного отличаются. Поскольку они существуют на протяжении всего потока приложения, они устанавливаются в обмене, а не в его «входящем компоненте» или «исходящем компоненте». , написав exchange.setProperty («some_property_name», «some_property_value»).

Что касается использования процессора в маршрутизаторе, его просто нужно создать в классе Router и вызвать с помощью .process (processorName). См. Пример ниже:

Вот он в действии:

Чтобы лучше понять эту концепцию, вы можете представить маршруты Camel как граф, имеющий процессоры в качестве узлов, соединенных линиями, соединяющими выход одного процессора со входом другого.

Вызов внешнего API

С Camel очень просто работать с внешними API. В этом примере проекта мы будем использовать API стека погоды, который предоставляет конечную точку, которая возвращает текущую информацию о погоде на основе параметра местоположения. Наше приложение откроет конечную точку, которая даст совет, что надеть в зависимости от погоды: если холодно, предложит принести свитер, если идет дождь, зонт. Если солнечно, порекомендуют солнцезащитный крем.

Давайте сначала посмотрим, как настроить маршрут:

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

Конечная точка получает единственный параметр запроса: город, погоду в котором мы хотим узнать. Конечная точка Camel получает его как заголовок с именем, который мы затем преобразуем в свойство, чтобы иметь к нему доступ позже. И свойство, и заголовок названы «city» - константа, которую мы разработали с именем CITY_TAG.

Перед выполнением вызова API мы удаляем все заголовки, чтобы убедиться, что отправляем только те, которые необходимы. Затем мы переходим к установке заголовка HTTP_METHOD (в этом случае мы будем выполнять запрос GET).

В следующей строке мы встречаем то, чего раньше не видели: предложение .toD. Мы видели предложение .to, но что означает буква D? Это означает, что строка, отправляемая в качестве параметра, является динамической, что означает, что она будет определена во время выполнения. Что это значит? Во-первых, давайте проверим метод, который генерирует URL-адрес службы:

URL-адрес, который мы хотим создать этим методом, например:

Http://api.weatherstack.com/current?access_key=123&query= buenos + aires & units = m.

Однако это не жестко заданный URL, поскольку он зависит от значения параметра query (который представляет город), которого у нас не будет, пока пользователь не предоставит его. Итак, если бы мы использовали метод .to () вместо .toD (), полученный URL-адрес выглядел бы так:

Http://api.weatherstack.com/current?access_key=123&query= $ {property.city} & units = m

Поскольку URL-адрес будет определен при компиляции приложения и создании маршрутов. Метод .toD устраняет эту проблему.

После вызова API мы демаршалируем результат из JSON в созданный нами объект POJO с именем WeatherResponse, который содержит поля, необходимые для нашего приложения.

И последнее, но не менее важное: мы вызываем процессор, который решает, что рекомендовать в зависимости от погоды: WeatherAdviserProcessor. Давайте посмотрим, как это работает:

Этот процессор не сложнее запрограммированного нами ранее, только немного длиннее. Логика, включенная в этот процессор, просто анекдотична.

А что касается конечного результата:

Заключение

В этой статье мы рассмотрели некоторые ключевые моменты, касающиеся разработки, ориентированной на сообщения, с использованием инфраструктуры Apache Camel.

Как мы упоминали ранее, он позволяет разработчикам интегрировать несколько технологий и обмениваться информацией с различными типами конечных точек, такими как файлы, очереди и внешние службы, при этом его легко изучить. Это также фреймворк с открытым исходным кодом, который делает его идеальным, чтобы бесплатно опробовать и посмотреть, как он работает для конкретного проекта.

При этом, если вашему проекту требуется много источников данных и мест назначения, как тот, над которым работала наша команда для банковской отрасли, фреймворк Camel определенно стоит попробовать.

Если вы хотите узнать больше об Apache Camel, вы можете взглянуть на его официальную документацию.