Статьи

ActiveMQ: как запустить / остановить верблюжий маршрут на ведомом устройстве ActiveMQ

Есть ли у вас бизнес-требования, при которых вам нужен 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.