Статьи

Собственно работающий мул в OpenShift


В этой статье я покажу, как вы можете запускать Mule в OpenShift без использования контейнера Servlet, и покажу, как я преодолел несколько препятствий реализации.

Если вы знакомы с Mule, вы знаете, что он предоставляет вам множество вариантов развертывания, включая как автономное развертывание, так и встраивание себя в приложение Java или Webapp. Рекомендуемый подход — запускать Mule ESB в автономном режиме из командной строки, в качестве службы или демона или из сценария. Это самая простая архитектура, поэтому она уменьшает количество точек, в которых могут возникать ошибки. Как правило, она также лучше всего подходит для производительности, поскольку уменьшает количество уровней и устраняет внутреннее влияние сервера приложений на производительность в целом. В Mule 3.x теперь вы также можете запускать несколько приложений бок о бок в экземпляре Mule, используя новую модель развертывания, которая может поддерживать оперативное развертывание и горячее повторное развертывание приложений. И, наконец,В автономном режиме полностью поддерживается модуль высокой доступности Mule и консоль управления Mule.

OpenShift предоставляет вам широкий выбор для разработки и развертывания приложений в облаке. Вы можете выбрать между PHP, Ruby, Perl, Python, Node.js или Java. Поскольку Mule основан на Java, мы в значительной степени охвачены. OpenShift предоставляет сквозной стек приложений Java, в том числе: Java EE6, CDI / WeldSpring и Spring. Вы можете выбирать между несколькими серверами приложений для веб-приложений, включая JBoss AS7, JBoss EAP6, Tomcat и GlassFish. Но если вы хотите запускать Mule в автономном режиме для вышеупомянутых преимуществ, вам необходимо создать картридж / приложение «сделай сам».

Приложение «Сделай сам» — это всего лишь простое приложение, без предварительно загруженного сервера, готовое к адаптации к вашим потребностям. С этим типом приложения OpenShift начинает стирать грань между IaaS и PaaS, предоставляя вам контролируемую и масштабируемую среду и в то же время предоставляя вам свободу для внедрения технологии, которая наилучшим образом соответствует вашим потребностям.

Начиная

Прежде чем пытаться создать DIY-приложение в OpenShift, вы должны ознакомиться с технологией, которую вы собираетесь использовать. У вас должно быть четкое понимание шагов, необходимых для настройки всего этого на вашей рабочей станции, а затем воспроизвести его в OpenShift.

Для приложения Mule нам не понадобится JBoss или какой-либо сервер приложений, даже контейнер сервлетов. Нам просто нужно установить Mule и запустить его.

Сделать это на собственной рабочей станции так же просто, как загрузить Mule, разархивировать его и запустить:

./mule start

И чтобы остановить Мул, мы выпускаем:

./mule stop

Теперь нам нужно сделать то же самое на нашем сервере в OpenShift. Сначала давайте создадим новое приложение с именем «mule»:

rhc app create -a mule -t diy-0.1

Now let's see what we created:

rhc app show -a mule

Теперь посмотрим, что мы создали. Запустите следующий скрипт:

rhc app show -a mule

Должен выводить аналогично следующему:

Application Info
================
mule
   Framework: diy-0.1
   Creation: 2013-01-19T07:14:34-06:01
   UUID: youruuid
   Git URL: ssh://youruuid@mule-yourdomain.rhcloud.com/~/git/mule.git/
   Public URL: http://mule-yourdomain.rhcloud.com/

Вы можете перейти по адресу http://mule-yourdomain.rhcloud.com/, чтобы увидеть работающую страницу индекса по умолчанию. Это та же самая статическая страница, которую вы можете найти в raw / index.html

Теперь посмотрим, что у нас в репо:

cd mule
ls -a
.git # our local git repo
misc # empty dir, you can just deleted it, no one will miss it
.openshift/action_hooks # this is where our hook scripts are located
raw # it holds the static page
README # some info

Это довольно скромное приложение, но есть папка, которая нам очень интересна —  .openshift / action_hooks:

ls .openshift/actions_hooks
build  deploy  post_deploy  pre_build  start  stop

Установка мула

.openshift / action_hooks / pre_build

Сценарий pre_build используется для загрузки требуемой установки Mule и ее разархивирования.

# Get Install
curl -o ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1.tar.gz http://dist.codehaus.org/mule/distributions/mule-standalone-3.3.1.tar.gz

# Unzip
tar -zxvf ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1.tar.gz -C ${OPENSHIFT_DATA_DIR}

.openshift / action_hooks / старт

Затем, чтобы запустить сервер Mule:

cd ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/bin
./mule start

.openshift / action_hooks / стоп

И чтобы остановить сервер Mule:

cd ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/bin
 
./mule stop

Обновление Java Service Wrapper

Когда вы запускаете команду mule, она запускает скрипт mule.bat или mule.sh в вашем каталоге MULE_HOME / bin. Эти сценарии вызывают Java Service Wrapper. Java Service Wrapper от Tanuki Software — это необычный маленький инструмент, который помогает управлять вашим приложением и JVM, в которой оно выполняется. По умолчанию он использует сокеты для связи между собой и JVM. Но OpenShif очень ограничен в отношении того, какие IP-адреса и порты вы можете прослушивать.

По умолчанию текущий выпуск Mule 3.3.1 использует версию 3.5.7 Java Service Wrapper. Если вы попытаетесь запустить установку Mule по умолчанию в OpenShift, вы получите следующую ошибку:

"unable to bind listener to any port in the range 32000-32999. (Permission denied)"

Java Service Wrapper управляется файлом wrapper.conf, который находится в вашем каталоге MULE_HOME / conf и имеет множество настроек, включая настройку портов, которые может прослушивать оболочка. Помимо портов, OpenShift позволяет приложениям привязываться только к определенному IP-адресу через переменную среды OPENSHIFT_INTERNAL_IP. К сожалению, нет возможности конфигурации переопределить этот IP-адрес. Игра закончена!

Extra Life! В более поздней версии оболочки есть новый параметр конфигурации: wrapper.backend.type = PIPE, позволяющий избежать использования сокетов и использовать каналы вместо этого, чтобы обойти эту проблему.

Чтобы обновить оболочку, мы просто скачиваем более поздние библиотеки оболочек и заменяем их в каталоге MULE_HOME / lib.

.openshift / action_hooks / pre_build

# Remove wrapper
rm ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/boot/libwrapper-*
rm ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/boot/wrapper-*
 
# Get later version of wrapper
curl -o ${OPENSHIFT_DATA_DIR}wrapper-delta-pack-3.5.9.tar.gz http://wrapper.tanukisoftware.com/download/3.5.9/wrapper-delta-pack-3.5.9.tar.gz
    
# Unzip
tar -zxvf ${OPENSHIFT_DATA_DIR}wrapper-delta-pack-3.5.9.tar.gz -C ${OPENSHIFT_DATA_DIR}

# Remove Zip
rm ${OPENSHIFT_DATA_DIR}wrapper-delta-pack-3.5.9.tar.gz

# Copy and replace new wrapper files
cp ${OPENSHIFT_DATA_DIR}wrapper-delta-pack-3.5.9/lib/libwrapper-* ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/boot

cp ${OPENSHIFT_DATA_DIR}wrapper-delta-pack-3.5.9/lib/wrapper.jar ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/boot/wrapper-3.5.9.jar

rm ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/boot/exec/*

cp ${OPENSHIFT_DATA_DIR}wrapper-delta-pack-3.5.9/bin/wrapper-* ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/boot/exec

Обновить файл wrapper.conf новой конфигурацией. Мы берем копию исходного файла wrapper.conf, в которую внесены поправки, чтобы она содержала опцию wrapper.backend.type = PIPE, и включили ее в наше git-репо, чтобы мы могли заменить оригинал при сборке установки.

.openshift / action_hooks / pre_build

# Replace wrapper.conf
rm ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/conf/wrapper.conf

cp ${OPENSHIFT_REPO_DIR}wrapper.conf ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/conf

Развертывание приложения Mule

Развертывание приложения так же просто, как копирование архива приложения Mule в необходимый каталог:

.openshift / action_hooks / развернуть

cp ${OPENSHIFT_REPO_DIR}helloworld.zip ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/apps/

Где helloworld.zip — это простое приложение Mule, предоставляемое через HTTP и возвращающее «Hello World».

<flow name="HelloWorldFlow">
   <http:inbound-endpoint  exchange-pattern="request-response" host="${OPENSHIFT_INTERNAL_IP}" port="8080" />
    
    <set-payload value="Hello World!" />
</flow>

Единственное, на что следует обратить внимание, это то, что мы используем переменную окружения $ {OPENSHIFT_INTERNAL_IP}. Это рекомендуемый IP-адрес для создания соединений сокетов на локальном хосте. Типичные значения, такие как «localhost», «127.0.0.1» и «0.0.0.0», все заблокированы.

Однако, если вы попытаетесь использовать эту переменную среды в качестве хоста, вы получите ошибку, подобную следующей:

Permission denied (java.net.BindException) java.net.PlainSocketImpl:-2 (null) 2. Failed to bind to uri "http://127.8.109.1:8080"

Как вы видете; внутренний IP-адрес разрешается нормально, и мы используем 8080, который является рекомендуемым портом для HTTP-соединений, но все еще не имеет значения

Взлом TCP транспорта

После копания в источнике возникает небольшая проблема с TCP-транспортом Mules.

public ServerSocket createServerSocket(URI uri, int backlog, Boolean reuse) throws IOException {
    String host = StringUtils.defaultIfEmpty(uri.getHost(), "localhost");
    InetAddress inetAddress = InetAddress.getByName(host);
    if (inetAddress.equals(InetAddress.getLocalHost())
            || inetAddress.isLoopbackAddress()
            || host.trim().equals("localhost")){
        return createServerSocket(uri.getPort(), backlog, reuse);
    }
    else {
        return createServerSocket(inetAddress, uri.getPort(), backlog, reuse);
    }
}

public ServerSocket createServerSocket(InetAddress address, int port, int backlog, Boolean reuse) throws IOException {
    return configure(new ServerSocket(), reuse, new InetSocketAddress(address, port), backlog);
}

public ServerSocket  createServerSocket(int port, int backlog, Boolean reuse) throws IOException {
    return configure(new ServerSocket(), reuse, new InetSocketAddress(port), backlog);
}

В данном случае внутренний IP является адресом обратной связи, поэтому Mule направляет его по пути создания Socket, который прослушивает все интерфейсы для этого порта. К счастью, в следующем выпуске 3.4 уже есть исправление — MULE-6584: HTTP / TCP, связанный с 127.0.0.1, прослушивает все интерфейсы .

К сожалению, это только в ближайшее время. Поэтому вместо этого я сам исправил источник этого транспорта для той же функциональности и включил получившуюся банку как часть моего проекта diy, чтобы заменить оригинальную банку с транспортом.

.openshift / action_hooks / pre_build

cp ${OPENSHIFT_REPO_DIR}mule-transport-tcp-3.3.1.jar ${OPENSHIFT_DATA_DIR}mule-standalone-3.3.1/lib/mule

Вот и все!

Если вы посмотрите на свое приложение по адресу: http://mule-yourdomain.rhcloud.com/, вы должны увидеть «Hello World»! Полный проект DIY с инструкциями можно найти на GitHub: https://github.com/ryandcarter/mule-diy-cartridge.