Шаблоны корпоративной интеграции
EIP можно использовать для разделения задач интеграции на более мелкие части и моделирования их с использованием стандартизированной графики. Каждый может легко понять эти модели. Кроме того, нет необходимости каждый раз изобретать велосипед для каждой проблемы интеграции.
Используя EIP, Apache Camel устраняет разрыв между моделированием и реализацией. Между моделями EIP и DSL Apache Camel существует почти однозначное отношение. В этой статье объясняется взаимосвязь EIP и Apache Camel на примере интернет-магазина.
Вариант использования: обработка заказов в интернет-магазине
Основные понятия Apache Camel вводятся путем реализации небольшого варианта использования. Начать свой собственный проект должно быть очень легко после прочтения этой статьи. Самый простой способ начать использовать архетип Maven [4]. Таким образом, вы можете перестроить следующий пример в течение нескольких минут. Конечно, вы также можете скачать весь пример сразу [5].
На рисунке 1 показан пример с точки зрения EIP. Задача — оформить заказы интернет-магазина. Заказы поступают в формате CSV. Сначала заказы должны быть преобразованы во внутренний формат. Элементы заказа каждого заказа должны быть разделены, потому что магазин продает только DVD и CD. Другие позиции заказа передаются партнеру.
Рисунок 1 : Перспектива EIP для проблемы интеграции
Этот пример демонстрирует преимущества EIP: проблема интеграции разбита на несколько небольших, постоянных подзадач. Эти подзадачи легко понять и каждый раз решать одинаково. После описания варианта использования мы рассмотрим основные понятия Apache Camel.
Базовые концепты
Apache Camel работает на виртуальной машине Java (JVM). Большинство компонентов реализованы на Java. Хотя это не является обязательным требованием для новых компонентов. Например, компонент camel-scala написан на языке Scala. Среда Spring используется в некоторых частях, например, для поддержки транзакций. Тем не менее, Spring-зависимости были сведены к минимуму в версии 2.9 [6]. Ядро Apache Camel очень мало и содержит только часто используемые компоненты (например, соединители с несколькими технологиями и API), такие как Log, File, Mock или Timer.
Дополнительные компоненты могут быть легко добавлены благодаря модульной структуре Apache Camel. Maven рекомендуется для управления зависимостями, поскольку для большинства технологий требуются дополнительные библиотеки. Тем не менее, библиотеки также могут быть загружены вручную и добавлены в путь к классам, конечно.
Основная функциональность Apache Camel — это механизм маршрутизации. Он распределяет сообщения на основе связанных маршрутов. Маршрут содержит логику потока и интеграции. Он реализован с использованием EIP и определенного DSL. Каждое сообщение содержит тело, несколько заголовков и дополнительные вложения. Сообщения отправляются от поставщика к потребителю. Между ними сообщения могут быть обработаны, например, отфильтрованы или преобразованы. На рисунке 1 показано, как сообщения могут изменяться в рамках маршрута.
Сообщения между поставщиком и потребителем управляются контейнером обмена сообщениями, который содержит уникальный идентификатор сообщения, информацию об исключительной ситуации, входящие и исходящие сообщения (т. Е. Запрос и ответ) и используемый шаблон обмена сообщениями (MEP). MEP «In Only» используется для односторонних сообщений, таких как JMS, тогда как MEP «In Out» выполняет обмен запросом-ответом, такой как запрос на основе HTTP на стороне клиента, и его ответ со стороны сервера.
После краткого объяснения основных понятий Apache Camel, следующие разделы дадут больше деталей и примеров кода. Начнем с архитектуры Apache Camel.
Архитектура
На рисунке 2 показана архитектура Apache Camel. CamelContext предоставляет систему времени выполнения. Внутри процессоры обрабатывают вещи между конечными точками, такие как маршрутизация или преобразование. Конечные точки соединяют несколько технологий для интеграции. Apache Camel предлагает различные DSL для решения проблем интеграции.
Рисунок 2 : Архитектура Apache Camel
CamelContext
CamelContext — это система времени выполнения Apache Camel, которая объединяет различные концепции, такие как маршруты, компоненты или конечные точки. В следующем фрагменте кода показан основной метод Java, который запускает CamelContext и останавливает его через 30 секунд. Обычно CamelContext запускается при загрузке приложения и останавливается при завершении работы.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
public class CamelStarter { public static void main(String[] args) throws Exception { CamelContext context = new DefaultCamelContext(); context.addRoutes( new IntegrationRoute()); context.start(); Thread.sleep( 30000 ); context.stop(); } } |
Система времени выполнения может быть включена в любом месте среды JVM, включая веб-контейнер (например, Tomcat), сервер приложений JEE (например, IBM WebSphere AS), контейнер OSGi или даже в облако.
Специфичные для домена языки
DSL облегчают реализацию сложных проектов, используя более высокий уровень абстракции. Apache Camel предлагает несколько разных DSL. Java, Groovy и Scala используют объектно-ориентированные концепции и предлагают специальный метод для большинства EIP. С другой стороны, Spring XML DSL основан на среде Spring и использует конфигурацию XML. Кроме того, OSGi blueprint XML доступен для интеграции с OSGi.
Java DSL имеет лучшую поддержку IDE. Groovy и Scala DSL похожи на Java DSL, кроме того, они предлагают типичные возможности современных языков JVM, такие как сжатый код или замыкания. В отличие от этих языков программирования, Spring XML DSL требует много XML. Кроме того, он предлагает очень мощный механизм внедрения зависимостей на основе Spring и удобные абстракции для упрощения конфигурации (например, соединений JDBC или JMS). Выбор — дело вкуса в большинстве случаев. Даже комбинация возможна. Многие разработчики используют Spring XML для конфигурации, в то время как маршруты реализованы в Java, Groovy или Scala. Маршруты
Маршруты являются важной частью Apache Camel. Порядок и логика интеграции указаны здесь. В следующем примере показан маршрут с использованием Java DSL:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class IntegrationRoute extends RouteBuilder { @Override public void configure() throws Exception { from(“file:target/inbox”) .process( new LoggingProcessor()) .bean( new TransformationBean(), “makeUpperCase”) .to(“file:target/outbox/dvd”); } } |
DSL прост в использовании. Каждый должен быть в состоянии понять приведенный выше пример, даже не зная Apache Camel. Маршрут реализует часть описанного варианта использования. Заказы размещаются в файловой директории из внешнего источника. Заказы обрабатываются и, наконец, перемещаются в целевой каталог.
Маршруты должны расширять класс «RouteBuilder» и переопределять метод «configure». Сам маршрут начинается с конечной точки «от» и заканчивается в одной или нескольких конечных точках «до». В промежутке реализована вся необходимая логика процесса. В одном методе «configure» может быть реализовано любое количество маршрутов.
В следующем фрагменте показан тот же маршрут, реализованный с помощью Spring XML DSL:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<beans … > <bean class =”mwea.TransformationBean” id=”transformationBean”/> <bean class =”mwea.LoggingProcessor” id=”loggingProcessor”/> <camelContext xmlns=”http: //camel.apache.org/schema/spring”> < package >mwea</ package > <route> <from uri=”file:target/inbox”/> <process ref=”loggingProcessor”/> <bean ref=”transformationBean”/> <to uri=”file:target/outbox”/> </route> </camelContext> </beans> |
Помимо маршрутов, другой важной концепцией Apache Camel являются его компоненты. Они предлагают точки интеграции практически для любой технологии.
Составные части
Тем временем доступно более 100 компонентов. Помимо широко распространенных технологий, таких как HTTP, FTP, JMS или JDBC, поддерживаются многие другие технологии, включая облачные сервисы от Amazon, Google, GoGrid и другие. Новые компоненты добавляются в каждом выпуске. Часто сообщество также создает новые пользовательские компоненты, потому что это очень просто.
Самая удивительная особенность Apache Camel — это его однородность. Все компоненты используют одинаковый синтаксис и понятия. Каждая интеграция и даже ее автоматические модульные тесты выглядят одинаково. Таким образом, сложность значительно уменьшается. Попробуйте изменить приведенный выше пример: если заказы следует отправлять в очередь JMS вместо каталога файлов, просто измените конечную точку «to» с «file: target / outbox» на «jms: queue: orders». Это оно! (JMS должен быть настроен один раз внутри приложения, конечно)
В то время как компоненты предлагают интерфейс для технологий, процессоры и компоненты могут использоваться для добавления настраиваемой логики интеграции в маршрут.
Процессоры и бобы
Помимо использования EIP, вам часто приходится добавлять индивидуальную логику интеграции. Это очень просто и снова всегда использует одни и те же понятия: процессоры или бины. Оба были использованы в примере маршрута выше.
Процессор — это простой интерфейс Java с одним методом: «процесс». Внутри этого метода вы можете делать все, что вам нужно для решения проблемы интеграции, например, преобразовывать входящее сообщение, вызывать другие службы и так далее.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public class LoggingProcessor implements Processor { @Override public void process(Exchange exchange) throws Exception { System.<em>out</em>.println(“Received Order: ” + exchange.getIn().getBody(String. class )); } } |
Параметр «exchange» содержит Messsage Exchange с входящим сообщением, исходящим сообщением и другой информацией. Благодаря реализации интерфейса Processor у вас есть зависимость от Camel API. Это может быть проблемой иногда. Может быть, у вас уже есть существующий код интеграции, который нельзя изменить (т.е. вы не можете реализовать интерфейс процессора)? В этом случае вы можете использовать Бины, также называемые POJO (Plain Old Java Object). Вы получаете входящее сообщение (которое является параметром метода) и возвращаете исходящее сообщение, как показано в следующем фрагменте:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public class TransformationBean { public String makeUpperCase(String body) { String transformedBody = body.toUpperCase(); return transformedBody; } } |
Вышеуказанный компонент получает строку, преобразует ее и, наконец, отправляет на следующую конечную точку. Посмотрите на маршрут выше снова. Входящее сообщение является файлом. Вы можете спросить, почему это работает? Apache Camel предлагает еще одну мощную функцию: более 150 автоматических преобразователей типов включены с нуля, например FileToString, CollectionToObject [] или URLtoInputStream. Кстати: другие конвертеры типов могут быть легко созданы и добавлены в CamelContext [7].
Если Бин содержит только один единственный метод, он даже может быть опущен в маршруте. Таким образом, вышеуказанный вызов также может быть .bean (new TransformationBean ()) вместо .bean (new TransformationBean (), «makeUpperCase»).
Добавление еще нескольких корпоративных шаблонов интеграции
Вышеуказанный маршрут преобразует входящие заказы, используя EIP Translator перед их обработкой. Помимо этого преобразования, требуется еще немного работы для реализации всего варианта использования. Поэтому в следующем примере используются еще несколько EIP:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class IntegrationRoute extends RouteBuilder { @Override public void configure() throws Exception { from(“file:target/inbox”) .process( new LoggingProcessor()) .bean( new TransformationBean()) .unmarshal().csv() .split(body().tokenize(“,”)) .choice() .when(body().contains(“DVD”)) .to(“file:target/outbox/dvd”) .when(body().contains(“CD”)) .to(“activemq:CD_Orders”) .otherwise() .to(“mock:others”); } } |
Каждый CSV-файл иллюстрирует один отдельный заказ, содержащий один или несколько элементов заказа. Компонент camel-csv используется для преобразования сообщения csv. После этого Splitter EIP разделяет каждый элемент заказа в теле сообщения. В этом случае используется разделитель по умолчанию (запятая). Хотя сложные регулярные выражения или языки сценариев, такие как XPath, XQuery или SQL, также могут использоваться в качестве разделителя.
Каждый элемент заказа должен быть отправлен в определенную единицу обработки (помните: есть заказы DVD, заказы CD и другие заказы, которые отправляются партнеру). Контент-маршрутизатор EIP решает эту проблему без каких-либо индивидуальных усилий по кодированию. Заказы на DVD обрабатываются с помощью файлового каталога, в то время как заказы на CD отправляются в очередь JMS.
ActiveMQ используется как реализация JMS в этом примере. Чтобы добавить поддержку ActiveMQ в приложение Camel, вам нужно всего лишь добавить связанную зависимость maven для компонента camel-activemq или добавить JAR-файлы в classpath вручную. Вот и все. Некоторым другим компонентам нужно немного больше конфигурации, один раз. Например, если вы хотите использовать WebSphere MQ или другую реализацию JMS вместо ActiveMQ, вам нужно настроить JMS-провайдера.
Все остальные элементы заказа, кроме DVD и CD, отправляются партнеру. К сожалению, этот интерфейс пока недоступен. Вместо этого используется компонент Mock для мгновенного моделирования этого интерфейса.
Приведенный выше пример впечатляюще показывает, как разные интерфейсы (в данном случае File, JMS и Mock) могут использоваться в рамках одного маршрута. Вы всегда применяете один и тот же синтаксис и понятия, несмотря на очень разные технологии.
Автоматические модульные и интеграционные тесты
Автоматические тесты имеют решающее значение. Тем не менее, это обычно игнорируется в интеграционных проектах. Причина — слишком большие усилия и очень высокая сложность из-за нескольких разных технологий.
Apache Camel решает эту проблему: предлагает поддержку тестирования через расширения JUnit. Тестовый класс должен расширять CamelTestSupport для использования мощных возможностей тестирования Camel. Помимо дополнительных утверждений, mocks поддерживаются неявно. Никакие другие фальшивые рамки, такие как EasyMock или Mockito, не требуются. Вы даже можете смоделировать отправку сообщений на маршрут или получение сообщений от него через шаблон производителя или потребителя. Все маршруты могут быть проверены автоматически с помощью этого набора. Стоит отметить, что синтаксис и концепции одинаковы для всех технологий.
В следующем фрагменте кода показан модульный тест для нашего примера маршрута:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
public class IntegrationTest extends CamelTestSupport { @Before public void setup() throws Exception { super .setUp(); context.addRoutes( new IntegrationRoute()); } @Test public void testIntegrationRoute() throws Exception { // Body of test message containing several order items String bodyOfMessage = “Harry Potter / dvd, Metallica / cd, Claus Ibsen – Camel in Action / book “; // Initialize the mock and set expected results MockEndpoint mock = context.getEndpoint(“mock:others”, MockEndpoint. class ); mock.expectedMessageCount( 1 ); mock.setResultWaitTime( 1000 ); // Only the book order item is sent to the mock // (because it is not a cd or dvd) String bookBody = “Claus Ibsen – Camel in Action / book”.toUpperCase(); mock.expectedBodiesReceived(bookBody); // ProducerTemplate sends a message (i.e. a File) to the inbox directory template.sendBodyAndHeader(“file: //target/inbox”, bodyOfMessage, Exchange.<em>FILE_NAME</em>, “order.csv”); Thread.sleep( 3000 ); // Was the file moved to the outbox directory? File target = new File(“target/outbox/dvd/order.csv”); assertTrue(“File not moved!”, target.exists()); // Was the file transformed correctly (i.e. to uppercase)? String content = context.getTypeConverter().convertTo(String. class , target); String dvdbody = “Harry Potter / dvd”.toUpperCase(); assertEquals(dvdbody, content); // Was the book order (i.e. „Camel in action“ which is not a cd or dvd) sent to the mock? mock.assertIsSatisfied(); } } |
Метод установки создает экземпляр CamelContext (и делает некоторые дополнительные вещи). После этого маршрут добавляется таким образом, чтобы его можно было проверить. Сам тест создает насмешку и устанавливает свои ожидания. Затем шаблон производителя отправляет сообщение в конечную точку маршрута «от». Наконец, некоторые утверждения подтверждают результаты. Тест можно запустить так же, как и любой другой тест JUnit: непосредственно в среде IDE или внутри скрипта сборки. Возможна даже гибкая разработка через тестирование (TDD). Во-первых, тест Camel должен быть написан до реализации соответствующего маршрута.
Если вы хотите узнать больше об Apache Camel, первым адресом должна стать книга «Верблюд в действии» [8], в которой подробно описываются все основы и многие дополнительные функции, включая примеры рабочего кода для каждой главы. После поднятия аппетита давайте теперь обсудим, когда использовать Apache Camel…
Альтернативы для системной интеграции
На рисунке 3 показаны три варианта интеграции приложений:
- Собственное индивидуальное решение : внедрите индивидуальное решение, которое работает для вашей проблемы, не разделяя проблемы на маленькие кусочки. Это работает и, вероятно, является самой быстрой альтернативой для небольших случаев использования. Вы должны кодировать все самостоятельно.
- Интеграционная платформа : используйте платформу, которая помогает интегрировать приложения стандартизированным способом, используя несколько шаблонов интеграции. Это значительно уменьшает усилия. Каждый разработчик легко поймет, что вы сделали. Вам не нужно каждый раз изобретать велосипед.
- Enterprise Service Bus (ESB) : используйте ESB для интеграции ваших приложений. Под капотом ESB часто также использует интеграционные рамки. Но есть гораздо больше функциональных возможностей, таких как управление бизнес-процессами, реестр или мониторинг деловой активности. Обычно вы можете настроить маршрутизацию и тому подобное в графическом пользовательском интерфейсе (вы должны решить самостоятельно, если это уменьшает сложность и усилия). Обычно ESB — сложный продукт. Кривая обучения намного выше, чем при использовании легкой интегрированной среды. Тем не менее, поэтому вы получаете очень мощный инструмент, который должен отвечать всем вашим требованиям в крупных интеграционных проектах.
Если вы решите использовать инфраструктуру интеграции, у вас все еще есть три хороших альтернативы в среде JVM: Spring Integration [9], Mule [10] и Apache Camel. Все они легки, просты в использовании и внедрении EIP. Поэтому они предлагают стандартизированный способ интеграции приложений и могут использоваться даже в очень сложных интеграционных проектах. Более подробное сравнение этих трех интегрирующих структур можно найти в [11].
Мой личный фаворит — Apache Camel из-за его потрясающих Java, Groovy и Scala DSL в сочетании со многими поддерживаемыми технологиями. Spring Integration и Mule предлагают только конфигурацию XML. Я бы использовал Mule только в том случае, если мне нужны некоторые из его удивительных уникальных соединителей для проприетарных продуктов (таких как SAP, Tibco Rendevous, Oracle Siebel CRM, Paypal или IBM CICS Transaction Gateway). Я бы использовал Spring Integration только в существующем проекте Spring, и мне нужно было бы интегрировать широко распространенные технологии, такие как FTP, HTTP или JMS. Во всех остальных случаях я бы использовал Apache Camel.
Тем не менее: независимо от того, какую из этих облегченных интеграционных сред вы выберете, вам будет очень весело реализовывать сложные интеграционные проекты с минимальными усилиями. Помните: часто толстый ESB имеет слишком много функциональности и, следовательно, слишком много ненужной сложности и усилий. Используйте правильный инструмент для правильной работы!
Apache Camel готов к проектам интеграции предприятий
Apache Camel уже отметил свой четвертый день рождения в июле 2011 года [12] и представляет собой очень зрелый и стабильный проект с открытым исходным кодом. Он поддерживает все требования, которые будут использоваться в корпоративных проектах, такие как обработка ошибок, транзакции, масштабируемость и мониторинг. Коммерческая поддержка также доступна.
Наиболее важным преимуществом является наличие доступных DSL, множество компонентов для почти всех мыслимых технологий и тот факт, что один и тот же синтаксис и концепции могут использоваться всегда — даже для автоматических тестов — независимо от того, какие технологии необходимо интегрировать. Поэтому Apache Camel всегда следует оценивать как легкую альтернативу тяжелым ESB. Начните с загрузки примера этой статьи. Если вам нужна помощь или дополнительная информация, есть отличное сообщество и хорошо написанная книга.
Источники:
- [1] «Шаблоны корпоративной интеграции: проектирование, создание и развертывание решений для обмена сообщениями», ISBN: 0321200683, Грегор Хопе, Бобби Вульф
- [2] Apache Camel http://camel.apache.org
- [3] Внутренний DSL http://martinfowler.com/bliki/DomainSpecificLanguage.html
- [4] Архетипы верблюдов http://camel.apache.org/camel-maven-archetypes.html
- [5] Пример кода для этой статьи на github https://github.com/megachucky/camel-infoq
- [6] Снижение зависимости от Spring JAR http://davsclaus.blogspot.com/2011/08/apache-camel-29-reduced-dependency-on.html
- [7] Конвертер типов верблюдов http://camel.apache.org/type-converter.html
- [8] «Верблюд в действии», ISBN: 1935182366, Клаус Ибсен, Джонатан Ансти, Адриан Збарча
- [9] Spring Integration www.springsource.org/spring-integration
- [10] Mule ESB http://www.mulesoft.org
- [11] Сравнение Apache Camel, Mule ESB и Spring Integration http://www.kai-waehner.de/blog/2012/01/10/spoilt-for-choice-which-integration-framework-to-use-spring -Интеграция-мул-ESB-или-апаш-верблюд
- [12] Четвертый день рождения верблюда Апачи http://camel.apache.org/2011/07/07/happy-birthday-camel.html
Ссылка: Apache Camel Tutorial — Введение в EIP, маршруты, компоненты, тестирование и другие концепции от нашего партнера по JCG Кая Вахнера в блоге о блоге Java EE / SOA / Cloud Computing .