JBoss Fuse: Использование Camel для старта дочерних контейнеров

JBoss Fuse настройка автоматического запуска контейнеров при загрузке системы

Во первых надо создать wrapper для root по инструкции https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.1/html/Configuring_and_Running_Red_Hat_JBoss_Fuse/ESBAdminService.html#ESBAdminWrapperGenerate

Но вот для дочерних контейнеров использовать врапер не удобно:

  • На каждый новый контейнер нужно будет создавать и настраивать врапер;
  • Если контейнер запускается через врапер перезагружать его тоже нужно через него, используя команды windows сервисов, через веб консоль уже лучше не пытаться этого делать;
  • Если нужны дополнительные JVM параметры для старта, через админку нельзя задать, надо лезть в конфиг врапера.

Поэтому запускать дочерние контейнеры лучше через сервис Fabric8.

Fabric8 предоставляет OSGI сервис io.fabric8.api.FabricService https://github.com/jboss-fuse/fabric8/blob/1.2.0.redhat-6-3-x/fabric/fabric-api/src/main/java/io/fabric8/api/FabricService.java, который позволяет получать информацию о существующих контейнерах, а также управлять ими - все то, что можно делать через консоль или веб админку.

Можно все закодировать с помощью Apache Camel в blueprint контексте и тогда не нужно будет модуль создавать, а деплоить бандл прямо из профиля.

Создаем файл fabric-container-launcher-blueprint.xml и в нем описываем camel context. По таймеру, каждые 30 сек, получаем текущий контейнер, проверяем что он полностью стартовал. Сделано 2 режима: стартовать все дочерние контейнеры или стартовать по списку, который задается в настройках.

В итоге получилось:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
           xsi:schemaLocation="
         http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
         http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

    <cm:property-placeholder persistent-id="fabric.container.launcher" update-strategy="reload"/>

    <reference id="fabricService" interface="io.fabric8.api.FabricService"/>

    <bean id="startList" class="org.apache.commons.lang3.StringUtils" factory-method="split">
        <argument value="${fabric.container.launcher.startList}"/>
        <argument value=","/>
    </bean>

    <camelContext id="fabric-container-launcher-context" xmlns="http://camel.apache.org/schema/blueprint">
        <route id="launcher-scan">
            <from uri="timer:launcherScan?period={{fabric.container.launcher.rescanTimeout}}"/>
            <log message="Mode: {{fabric.container.launcher.mode}}"/>
            <setBody>
                <method ref="fabricService" method="getCurrentContainer"/>
            </setBody>
            <log message="Current container id: ${body.id} pending: ${body.isProvisioningPending}"/>
            <when>
                <simple>${body.isProvisioningPending} == true</simple>
                <log message="Current container provisioning pending, wait while complete" loggingLevel="INFO"/>
                <stop/>
            </when>

            <choice>
                <when>
                    <simple>${properties:fabric.container.launcher.mode} == "all"</simple>
                    <setBody>
                        <simple>${body.children}</simple>
                    </setBody>
                    <log message="Children containers count: ${body.length}"/>
                    <split>
                        <simple>${body}</simple>
                        <to uri="direct:startContainer"/>
                    </split>
                </when>
                <when>
                    <simple>${properties:fabric.container.launcher.mode} == "on"</simple>
                    <setBody>
                        <simple>${ref:startList}</simple>
                    </setBody>
                    <log message="StartList len: ${body.length}"/>
                    <split>
                        <simple>${body}</simple>
                        <to uri="bean:fabricService?method=getContainer(${body})"/>
                        <to uri="direct:startContainer"/>
                    </split>
                </when>
                <otherwise>
                    <log message="Launcher turn off" loggingLevel="INFO"/>
                </otherwise>
            </choice>
        </route>

        <route id="start-container">
            <from uri="direct:startContainer"/>
            <log message="Container: ${body.id} isEnsembleServer: ${body.isEnsembleServer} isRoot: ${body.isRoot} Alive: ${body.isAliveAndOK}
              Provision: Result=${body.provisionResult} - Status=${body.provisionStatus} - Pending=${body.isProvisioningPending}"/>
            <log message="PID: ${body.processId}"/>
            <when>
                <simple>${body.isRoot} != true &amp;&amp; ${body.isAlive} != true &amp;&amp; ${body.isEnsembleServer} !=
                    true &amp;&amp; ${body.isProvisioningPending} != true
                </simple>
                <log message="Starting container ${body.id}" loggingLevel="INFO"/>
                <setBody>
                    <simple>${body.start}</simple>
                </setBody>
                <delay>
                    <constant>{{fabric.container.launcher.startTimeout}}</constant>
                </delay>
            </when>
        </route>
    </camelContext>
</blueprint>

 

Создаем профиль, добавляем в него созданный blueprint context и properties файл fabric.container.launcher.properties с нужными настройками:

# all off on

fabric.container.launcher.mode=all

# used for "on" mode

fabric.container.launcher.startList=test-broker,test

 

fabric.container.launcher.rescanTimeout=30000

fabric.container.launcher.startTimeout=10000

 

и также файл io.fabric8.agent.properties в котором добавляем наш контекст и бандл с библиотекой commons-lang3

attribute.parents=feature-camel
bundle.blueprint\:profile\:fabric-container-launcher-blueprint.xml = blueprint:profile:fabric-container-launcher-blueprint.xml
bundle.mvn\:org.apache.commons/commons-lang3/3.4 = mvn:org.apache.commons/commons-lang3/3.4
 

Осталось добавить данный профиль в рутовый контейнер. Теперь, когда рутовый контейнер запущен, будут автоматически запускаться все нужные дочерние контейнеры.

 
Полный код профиля доступен на GitHub