В каждой работе, на которой я был до сих пор, люди так или иначе пишут свои собственные решения для решения многих общих проблем (или они покупают очень дорогие корпоративные ESB-серверы, на изучение, настройку и обслуживание которых уходят месяцы и месяцы). ). Вещи, которые мы обычно решаем, — это интеграция (склеивание) кода существующих бизнес-сервисов вместе, обработка данных определенным образом, или перемещение и преобразование данных из одного места в другое и т. Д. Это очень типичная потребность во многих ИТ-средах. Apache Camel может использоваться в подобных случаях; не только это, но и очень продуктивно и эффективно!
В этой статье я покажу вам, как начать работу с Apache Camel вместе с несколькими строками скрипта Groovy . Конечно, вы также можете начать с полноценного Java-проекта, чтобы опробовать Camel, но я считаю, что Groovy даст вам самый короткий рабочий пример и кривую обучения.
Начало работы с Apache Camel с использованием Groovy
Итак, начнем. Сначала давайте посмотрим демо «Привет, мир!» С Camel + Groovy.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@Grab ( 'org.apache.camel:camel-core:2.10.0' ) @Grab ( 'org.slf4j:slf4j-simple:1.6.6' ) import org.apache.camel.* import org.apache.camel.impl.* import org.apache.camel.builder.* def camelContext = new DefaultCamelContext() camelContext.addRoutes( new RouteBuilder() { def void configure() { from( 'timer://jdkTimer?period=3000' ) .to( 'log://camelLogger?level=INFO' ) } }) camelContext.start() addShutdownHook{ camelContext.stop() } synchronized ( this ){ this .wait() } |
Сохраните выше в файл с именем helloCamel.groovy
а затем запустите его так:
01
02
03
04
05
06
07
08
09
10
11
12
|
$ groovy helloCamel.groovy 388 [main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.10 . 0 (CamelContext: camel- 1 ) is starting 445 [main] INFO org.apache.camel.management.ManagementStrategyFactory - JMX enabled. 447 [main] INFO org.apache.camel.management.DefaultManagementLifecycleStrategy - StatisticsLevel at All so enabling load performance statistics 678 [main] INFO org.apache.camel.impl.converter.DefaultTypeConverter - Loaded 170 type converters 882 [main] INFO org.apache.camel.impl.DefaultCamelContext - Route: route1 started and consuming from: Endpoint[timer: //jdkTimer?period=3000] 883 [main] INFO org.apache.camel.impl.DefaultCamelContext - Total 1 routes, of which 1 is started. 887 [main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.10 . 0 (CamelContext: camel- 1 ) started in 0.496 seconds 898 [Camel (camel- 1 ) thread # 1 - timer: //jdkTimer] INFO camelLogger - Exchange[ExchangePattern:InOnly, BodyType:null, Body:[Body is null]] 3884 [Camel (camel- 1 ) thread # 1 - timer: //jdkTimer] INFO camelLogger - Exchange[ExchangePattern:InOnly, BodyType:null, Body:[Body is null]] 6884 [Camel (camel- 1 ) thread # 1 - timer: //jdkTimer] INFO camelLogger - Exchange[ExchangePattern:InOnly, BodyType:null, Body:[Body is null]] ... |
Небольшой сценарий выше прост, но в нем представлено несколько ключевых особенностей Camel Groovyness. Первый и последний раздел скрипта helloCamel.groovy
— это просто отличные персонажи Groovy. Аннотация @Grab
автоматически загрузит указанные вами банки зависимостей. Мы импортируем пакеты Java, чтобы использовать их классы позже. В конце мы завершим работу над Camel перед выходом из JVM через механизм Java Shutdown Hook. Программа будет сидеть и ждать, пока пользователь не нажмет CTRL+C
, как обычное поведение процесса на сервере.
В средней части находится действие «Верблюд». Вы всегда должны создать контекст Camel, чтобы начать (думать о нем как о сервере или менеджере процесса). А затем вы добавите маршрут Camel (представьте его как рабочий процесс или конвейер), который вам нравится обрабатывать данные (любит Camel) называть эти данные «сообщения»). Маршрут состоит из начальной точки «от» (где генерируются данные) и одной или нескольких точек «до» (где будут обрабатываться данные). Верблюд называет эти пункты назначения «точками» как «Конечными точками». Эти конечные точки могут быть выражены в простом формате строки URI, таком как 'timer://jdkTimer?period=3000'
. Здесь мы генерируем сообщение таймера каждые 3 секунды в потоке потока, а затем обрабатываем с помощью URI регистратора, который просто выводит на консольный вывод.
После запуска верблюжьего контекста он начнет обрабатывать данные в рабочем процессе, как вы можете видеть из приведенного выше примера вывода. Теперь попробуйте нажать CTRL+C
чтобы завершить процесс. Обратите внимание, как Верблюд очень изящно отключит все.
1
2
3
4
5
6
|
7312 [Thread- 2 ] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.10 . 0 (CamelContext: camel- 1 ) is shutting down 7312 [Thread- 2 ] INFO org.apache.camel.impl.DefaultShutdownStrategy - Starting to graceful shutdown 1 routes (timeout 300 seconds) 7317 [Camel (camel- 1 ) thread # 2 - ShutdownTask] INFO org.apache.camel.impl.DefaultShutdownStrategy - Route: route1 shutdown complete, was consuming from: Endpoint[timer: //jdkTimer?period=3000] 7317 [Thread- 2 ] INFO org.apache.camel.impl.DefaultShutdownStrategy - Graceful shutdown of 1 routes completed in 0 seconds 7321 [Thread- 2 ] INFO org.apache.camel.impl.converter.DefaultTypeConverter - TypeConverterRegistry utilization[attempts= 2 , hits= 2 , misses= 0 , failures= 0 ] mappings[total= 170 , misses= 0 ] 7322 [Thread- 2 ] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.10 . 0 (CamelContext: camel- 1 ) is shutdown in 0.010 seconds. Uptime 7.053 seconds. |
Так что это наш первый вкус езды на верблюде! Тем не менее, мы назвали этот раздел «Hello World!» демо, а еще мы не видели ни одного. Но вы, возможно, также заметили, что вышеприведенный скрипт — это в основном код, который мы установили. Пользовательская логика еще не была добавлена. Даже не запись части сообщения! Мы просто настраиваем маршрут.
Теперь давайте немного изменим скрипт, чтобы мы добавили нашу пользовательскую логику для обработки сообщения таймера.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Grab ( 'org.apache.camel:camel-core:2.10.0' ) @Grab ( 'org.slf4j:slf4j-simple:1.6.6' ) import org.apache.camel.* import org.apache.camel.impl.* import org.apache.camel.builder.* def camelContext = new DefaultCamelContext() camelContext.addRoutes( new RouteBuilder() { def void configure() { from( 'timer://jdkTimer?period=3000' ) .to( 'log://camelLogger?level=INFO' ) .process( new Processor() { def void process(Exchange exchange) { println( 'Hello World!' ) } }) } }) camelContext.start() addShutdownHook{ camelContext.stop() } synchronized ( this ){ this .wait() } |
Обратите внимание, как я могу просто добавить часть кода процесса сразу после строки to('log...')
. Я добавил кодовый блок «процессор» для обработки сообщения таймера. Логика проста: мы приветствуем мир на каждом тике.
Как сделать верблюжий маршрут более лаконичным и практичным
Теперь, ты уже в Привет? Если нет, то я надеюсь, что вы будете терпеливы и продолжите следить за некоторыми практическими особенностями Camel. Во-первых, если вы хотите использовать Camel в реальных условиях, я бы порекомендовал вам настроить бизнес-логику отдельно от определения маршрута рабочего процесса. Это сделано для того, чтобы вы могли четко выразить и увидеть весь поток маршрутов с первого взгляда. Для этого вы хотите переместить «процессор» в служебный компонент.
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
|
@Grab ( 'org.apache.camel:camel-core:2.10.0' ) @Grab ( 'org.slf4j:slf4j-simple:1.6.6' ) import org.apache.camel.* import org.apache.camel.impl.* import org.apache.camel.builder.* import org.apache.camel.util.jndi.* class SystemInfoService { def void run() { println( 'Hello World!' ) } } def jndiContext = new JndiContext(); jndiContext.bind( 'systemInfoPoller' , new SystemInfoService()) def camelContext = new DefaultCamelContext(jndiContext) camelContext.addRoutes( new RouteBuilder() { def void configure() { from( 'timer://jdkTimer?period=3000' ) .to( 'log://camelLogger?level=INFO' ) .to( 'bean://systemInfoPoller?method=run' ) } }) camelContext.start() addShutdownHook{ camelContext.stop() } synchronized ( this ){ this .wait() } |
Теперь посмотрите, насколько компактным стал этот рабочий процесс? Java DSL Camel, такой как 'from().to().to()'
для определения маршрута, настолько прост и удобен в использовании. Вы даже можете показать этот фрагмент кода своим бизнес-аналитикам, и они, вероятно, смогут легко проверить ваш бизнес-поток! Разве это не стоит одного миллиона долларов?
Как насчет другой демонстрации: Обработка FilePoller
Обработка опроса файлов является очень распространенным и эффективным способом решения многих бизнес-задач. Если вы работаете в коммерческих компаниях достаточно долго, вы, возможно, уже написали его раньше. Типичный файл-поллер обрабатывает входящие файлы из каталога, затем обрабатывает содержимое, а затем перемещает файл в выходной каталог. Давайте сделаем верблюжий маршрут, чтобы сделать именно это.
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
|
@Grab ( 'org.apache.camel:camel-core:2.10.0' ) @Grab ( 'org.slf4j:slf4j-simple:1.6.6' ) import org.apache.camel.* import org.apache.camel.impl.* import org.apache.camel.builder.* import org.apache.camel.util.jndi.* class UpperCaseTextService { def String transform(String text) { return text.toUpperCase() } } def jndiContext = new JndiContext(); jndiContext.bind( 'upperCaseTextService' , new UpperCaseTextService()) def dataDir = '/${System.properties[' user.home ']}/test/file-poller-demo' def camelContext = new DefaultCamelContext(jndiContext) camelContext.addRoutes( new RouteBuilder() { def void configure() { from( 'file://${dataDir}/in' ) .to( 'log://camelLogger' ) .to( 'bean://upperCaseTextService?method=transform' ) .to( 'file://${dataDir}/out' ) } }) camelContext.start() addShutdownHook{ camelContext.stop() } synchronized ( this ){ this .wait() } |
Здесь вы видите, что я определил маршрут для опроса $HOME/test/file-poller-demo/in
текстовых файлах. Как только он найден, он регистрирует его в консоли, а затем обрабатывает с помощью службы, которая преобразует текст содержимого в верхний регистр. После этого он отправит файл в каталог $HOME/test/file-poller-demo/out
. Боже мой, прочитав вышеприведенный маршрут «Верблюд», я могу выразить то, что я записал, столь же эффективно. Видите ли вы преимущества здесь?
Что такое «батарейки» входит в комплект.
Если вы раньше использовали программирование на Python, возможно, вы слышали фразу, которую они часто утверждают: в Python включены «батареи». Это означает, что их интерпретатор поставляется с богатыми библиотеками для большинства общих потребностей программирования. Вы часто можете написать программу на Python без необходимости загружать отдельные внешние библиотеки.
Я делаю аналогичные аналогии здесь с Apache Camel. Проект Camel поставляется с таким количеством готовых к использованию компонентов, что вы можете найти практически любой транспортный протокол, который может нести данные. Эти компоненты Camel поддерживают разные URI конечной точки, которые мы видели в наших демонстрациях выше. Мы просто показали вам bean
timer
, log
, bean
и file
, но их более 120. Вы найдете jms
, http
, ftp
, cfx
или tcp
чтобы назвать несколько.
В проекте Camel также есть возможность определить маршрут в декларативном формате xml . Xml — это просто расширение конфигурации Spring xml с обработчиком пространства имен Camel, добавленным сверху. Spring не обязателен для Camel, но вы можете использовать его вместе очень мощным способом.
Ссылка: Начало работы с Apache Camel с использованием Groovy от нашего партнера по JCG Земьяна Дена в блоге журнала A Programmer’s Journal .