Есть ли у вас бизнес-требования, при которых вам нужен ActiveMQ для развертывания ваших маршрутов Camel, но вы поняли, что в конфигурации Master / Slave контекст Camel всегда запускается на подчиненном брокере?
В этом примере я покажу вам, как вы можете настроить ActiveMQ для развертывания маршрутов Camel, а также как контролировать, когда эти маршруты должны быть запущены. В этом примере у нас есть мастер-брокер с маршрутами, которые запускаются при запуске брокера. Кроме того, у нас будет подчиненный брокер, у которого будут маршруты, которые мы хотим запустить только тогда, когда ведомое устройство станет ведущим.
В настоящее время я использую apache-activemq-5.5.1-fuse-04-01, который является последней версией ActiveMQ от FuseSourceна момент написания этой статьи. Вы можете получить бинарные файлы / исходники по следующей ссылке: apache-activemq-5.5.1-fuse-04-01
Итак, вы можете спросить, как вам это удастся, не так ли? К счастью, у нас может быть что-то, работающее с небольшим кодом и небольшой конфигурацией.
Код
Код, который нам нужно реализовать, довольно прост. Нам просто нужно создать класс, который реализует интерфейс службы ActiveMQ . Ниже приведен простой пример, который я создал, чтобы продемонстрировать, как это работает:
package com.fusesource.example; import org.apache.activemq.Service; import org.apache.camel.spring.SpringCamelContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Example used to start and stop the camel context using the ActiveMQ Service interface * */ public class CamelContextService implements Service { private final Logger LOG = LoggerFactory.getLogger(CamelContextService.class); SpringCamelContext camel; @Override public void start() throws Exception { try { camel.start(); } catch (Exception e) { LOG.error("Unable to start camel context: " + camel); e.printStackTrace(); } } @Override public void stop() throws Exception { try { camel.stop(); } catch (Exception e) { LOG.error("Unable to stop camel context: " + camel); e.printStackTrace(); } } public SpringCamelContext getCamel() { return camel; } public void setCamel(SpringCamelContext camel) { this.camel = camel; } }
Волшебство всего этого находится в интерфейсе Сервиса. Когда этот класс зарегистрирован в качестве службы у посредника, метод start будет вызываться, когда посредник будет полностью инициализирован. Не забудьте скопировать файл jar в каталог lib брокера, в который вы хотите, чтобы этот код вызывался.
Конфигурация
Сначала давайте посмотрим, как мы развернем маршруты Camel из файла конфигурации брокера ActiveMQ. В каталоге установки брокера вы найдете каталог conf, в котором хранятся несколько примеров различных файлов конфигурации брокера и тому подобное. Один такой файл называется camel.xml, который определяет простой маршрут. В нашем примере мы импортируем этот файл в activemq.xml нашего брокера следующим образом, который запустит контекст верблюда и связанный маршрут.
<import resource="camel.xml"/>
Это должно быть добавлено сразу после конечного элемента посредника, где вы увидите, что конфигурация уже импортирует jetty.xml.
Теперь, когда мы добавили верблюжий маршрут к главному брокеру, его можно запустить. После запуска вы должны увидеть, что верблюжий контекст был выбран, и был запущен один маршрут:
INFO | Apache Camel 2.8.0-fuse-04-01 (CamelContext: camel) is starting INFO | JMX enabled. Using ManagedManagementStrategy. INFO | Found 3 packages with 14 @Converter classes to load INFO | Loaded 163 core type converters (total 163 type converters) INFO | Loaded 3 @Converter classes INFO | Loaded additional 4 type converters (total 167 type converters) in 0.006 seconds WARN | Broker localhost not started so using broker1 instead INFO | Connector vm://localhost Started INFO | Route: route1 started and consuming from: Endpoint[activemq://example.A] INFO | Total 1 routes, of which 1 is started. INFO | Apache Camel 2.8.0-fuse-04-01 (CamelContext: camel) started in 0.532 seconds
Итак, теперь, когда у нас есть главный брокер и запущен с развернутым маршрутом Camel, мы собираемся сделать то же самое с подчиненным брокером, но на этот раз мы собираемся немного отредактировать camel.xml следующим образом, чтобы установить идентификатор контекста Camel в camelBackup и, самое главное, мы собираемся добавить атрибут autoStartup и установить его в false, чтобы предотвратить запуск маршрута при обнаружении контекста Camel:
<camelContext id="camelBackup" xmlns="http://camel.apache.org/schema/spring" autoStartup="false">
И последнее, что нам нужно сделать с подчиненным брокером, — это настроить новый сервис, который мы создали из приведенного выше кода. Скопируйте следующую конфигурацию в файл activemq.xml вашего подчиненного брокера:
<services> <bean xmlns="http://www.springframework.org/schema/beans" class="com.fusesource.example.CamelContextService"> <property name="camel" ref="camelBackup"/> </bean> </services>
Из приведенной выше конфигурации и примера кода видно, что Spring используется для добавления свойства camel в наш класс Service. Кроме того, обратите внимание, что для ref было установлено значение camelBackup, то есть идентификатор, который мы использовали для CamelContext в файле camel.xml ведомого устройства.
Кроме того, посредник был настроен как подчиненный, поэтому он будет полностью инициализирован только в случае сбоя главного посредника. Если вам нужна дополнительная информация о настройке ведущих / подчиненных брокеров ActiveMQ, взгляните на одно из моих ранних сообщений о конфигурации главного / подчиненного брокера .
Если вы еще не сделали все это готовым, скопируйте созданный jar-файл из пакета кода из приведенного выше примера в каталог lib ведомого брокера.
Примечание. В производственной системе вы можете настроить это как на главном, так и на ведомом посредниках, чтобы сохранить конфигурации в зеркальном отображении, так как маршруты будут также запущены на главном сервере после его полной инициализации. В этом посте я оставляю необходимую конфигурацию подчиненному брокеру, чтобы продемонстрировать поведение.
Тестовый запуск
Теперь, когда у нас есть готовый код и конфигурация, давайте проведем тестовый запуск, запустив ведомого брокера.
INFO | Apache Camel 2.8.0-fuse-04-01 (CamelContext: camelBackup) is starting INFO | JMX enabled. Using ManagedManagementStrategy. INFO | Found 3 packages with 14 @Converter classes to load INFO | Loaded 163 core type converters (total 163 type converters) INFO | Loaded 3 @Converter classes INFO | Loaded additional 4 type converters (total 167 type converters) in 0.007 seconds INFO | Total 1 routes, of which 0 is started. INFO | Apache Camel 2.8.0-fuse-04-01 (CamelContext: camelBackup) started in 0.512 seconds
Просматривая выходные данные подчиненного брокера, вы можете увидеть, что CamelContext все еще запущен, однако маршрут не запущен (помните, что мы установили autoStartup = «false). Теперь в терминале, где работает главный брокер, выполните команду kill, чтобы остановить брокер.
Если вы снова посмотрите на выход ведомого брокера, то увидите, что соединитель был запущен, в данном случае — openwire, и теперь начинается маршрут Camel.
ERROR | Network connection between vm://broker2#0 and tcp://localhost/127.0.0.1:61616 shutdown: null java.io.EOFException at java.io.DataInputStream.readInt(DataInputStream.java:375) at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:275) at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:222) at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:214) at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:197) at java.lang.Thread.run(Thread.java:680) WARN | Master Failed - starting all connectors INFO | Listening for connections at: tcp://macbookpro-251a.home:62616 INFO | Connector openwire Started INFO | Apache Camel 2.8.0-fuse-04-01 (CamelContext: camelBackup) is starting WARN | Broker localhost not started so using broker2 instead INFO | Connector vm://localhost Started INFO | Route: route1 started and consuming from: Endpoint[activemq://example.A] INFO | Total 1 routes, of which 1 is started. INFO | Apache Camel 2.8.0-fuse-04-01 (CamelContext: camelBackup) started in 0.036 seconds
Заключение
Вот и все, что нужно сделать, и я думаю, вы согласитесь, что запуск маршрута от ведомого ActiveMQ довольно прост и легок в реализации. Я также хотел бы поблагодарить Хирама Кирино , основателя Apache ActiveMQ, за то, что он указал мне на направление использования сервисного интерфейса ActiveMQ.