5 августа 2026 г.
Docker Compose файл
Создадим файл docker-compose.yml:
services:
artemis:
image: apache/activemq-artemis:latest
container_name: artemis
ports:
- "61613:61613" # STOMP порт
- "61616:61616" # Мультипротокольный порт (опционально)
- "8161:8161" # Веб-консоль
environment:
- ARTEMIS_USER=admin
- ARTEMIS_PASSWORD=admin
volumes:
- artemis-data:/var/lib/artemis/data
- artemis-logs:/var/lib/artemis/log
restart: unless-stopped
volumes:
artemis-data:
driver: local
artemis-logs:
driver: local
Выполним команду в терминале из папки с docker-compose.yml. Флаг -d запускает контейнеры в фоновом режиме.
docker-compose up -d
Архитектура системы
ArtemisMQ Broker — это высокопроизводительный брокер сообщений на базе Apache ActiveMQ Artemis. В нашем случае используется официальный образ apache/activemq-artemis:latest, который предоставляет гибкую платформу для обмена сообщениями с поддержкой множества протоколов.
Сетевые порты
- Порт 61613 (STOMP): используется приложениями для отправки и получения сообщений через протокол STOMP (Simple Text Oriented Messaging Protocol). Этот протокол особенно удобен для веб-приложений и клиентов на JavaScript.
- Порт 61616 (мультипротокольный): основной порт для подключения по протоколам OpenWire, AMQP, MQTT и другим. Обеспечивает максимальную совместимость с различными клиентами.
- Порт 8161 (веб-консоль): предназначен для веб-интерфейса управления Artemis, где вы можете администрировать очереди, темы и наблюдать за работой брокера.
Веб-консоль управления
Встроенный веб-интерфейс Artemis — это мощный инструмент для мониторинга и администрирования.
- Адрес: http://localhost:8161
- Логин/Пароль: admin/admin (заданы в переменных окружения)
- Функциональность:
- Просмотр всех очередей, тем и адресов.
- Управление сообщениями: отправка, перемещение, удаление.
- Мониторинг количества сообщений в очередях, скорости обработки и задержек.
- Просмотр статистики по подключениям и сессиям.
- Управление пользователями и правами доступа.
Хранение данных
Для обеспечения сохранности данных и журналов используются два постоянных тома (volumes):
- artemis-data: хранит файлы данных брокера, включая все сохраняемые сообщения и метаданные очередей. Это гарантирует, что при перезапуске контейнера сообщения не будут потеряны.
- artemis-logs: содержит журналы работы брокера, которые помогают в диагностике проблем и аудите операций.
Perl скрипты
Producer (отправитель для одного сообщения)
Создадим файл
producer.pl. Этот скрипт на Perl демонстрирует пример производителя (producer) сообщений, который подключается к брокеру ArtemisMQ по протоколу STOMP и отправляет сообщение в очередь.
#!/usr/bin/perl
use strict;
use warnings;
use Net::STOMP::Client;
# --- Конфигурация подключения ---
my $STOMP_HOST = 'localhost';
my $STOMP_PORT = 61613;
my $STOMP_USER = 'admin';
my $STOMP_PASS = 'admin';
my $DESTINATION = '/queue/MyPerlQueue'; # Имя очереди
# --- Подключение к брокеру ---
my $stomp = Net::STOMP::Client->new(
host => $STOMP_HOST,
port => $STOMP_PORT,
);
# --- Аутентификация ---
$stomp->connect(
login => $STOMP_USER,
passcode => $STOMP_PASS,
);
# --- Отправка сообщения ---
$stomp->send(
destination => $DESTINATION,
body => 'Hello from Perl producer!',
'destination-type' => 'ANYCAST', # Для очередей
'persistent' => 'true', # Постоянное сообщение
'priority' => '4', # Приоритет от 0 до 9
'expires' => '0', # Бесконечное время жизни
);
print "[OK] Message sent to queue '$DESTINATION'\n";
# --- Отключение ---
$stomp->disconnect();
exit 0;
Заголовки (headers):
- destination-type: ANYCAST — указывает Artemis, что сообщение адресовано очереди (Anycast-семантика), а не теме (Multicast).
- persistent: true — сообщение будет сохранено на диск для надежности.
- priority: 4 — приоритет сообщения (от 0 — низший, до 9 — высший).
- expires: 0 — сообщение не имеет срока годности (хранится бесконечно).
Consumer (получатель для одного сообщения)
Создадим файл
consumer.pl. Этот скрипт на Perl демонстрирует пример потребителя (consumer) сообщений, который подключается к брокеру ArtemisMQ по протоколу STOMP, подписывается на очередь и получает из неё самое раннее (первое) сообщение с ручным подтверждением.
#!/usr/bin/perl
use strict;
use warnings;
use Net::STOMP::Client;
# --- Конфигурация подключения ---
my $STOMP_HOST = 'localhost';
my $STOMP_PORT = 61613;
my $STOMP_USER = 'admin';
my $STOMP_PASS = 'admin';
my $DESTINATION = '/queue/MyPerlQueue';
# --- Подключение к брокеру ---
my $stomp = Net::STOMP::Client->new(
host => $STOMP_HOST,
port => $STOMP_PORT,
);
# --- Аутентификация ---
$stomp->connect(
login => $STOMP_USER,
passcode => $STOMP_PASS,
);
# --- Подписка на очередь ---
$stomp->subscribe(
destination => $DESTINATION,
'subscription-type' => 'ANYCAST', # Для очередей
'ack' => 'client', # Ручное подтверждение
);
print "[INFO] Waiting for messages from '$DESTINATION'...\n";
# --- Получение одного сообщения ---
my $frame = $stomp->receive_frame();
if ($frame && $frame->command eq 'MESSAGE') {
my $body = $frame->body;
print "[RECEIVED] $body\n";
# Получаем ID для подтверждения
my $ack_id = $frame->headers->{'ack'};
if ($ack_id) {
eval { $stomp->ack('id' => $ack_id) };
if ($@) {
print "[WARNING] ACK failed: $@\n";
} else {
print "[ACK] Message acknowledged (ID: $ack_id)\n";
}
}
} else {
print "[ERROR] No message received\n";
}
# --- Отключение ---
$stomp->disconnect();
exit 0;
Заголовки (headers):
- subscription-type: ANYCAST — указывает Artemis, что подписка осуществляется на очередь (Anycast-семантика), а не на тему.
- ack: client — включает ручной режим подтверждения. Сообщение не будет удалено из очереди, пока клиент явно не отправит ACK.
Producer (отправитель для нескольких сообщений)
Создадим файл
producer_loop.pl. Этот скрипт демонстрирует производителя, который отправляет 10 сообщений в топик (а не в очередь). Он использует семантику MULTICAST, чтобы каждое сообщение было доставлено всем активным подписчикам.
#!/usr/bin/perl
use strict;
use warnings;
use Net::STOMP::Client;
use Time::HiRes qw(sleep); # Для паузы между сообщениями
# --- Конфигурация ---
my $STOMP_HOST = 'localhost';
my $STOMP_PORT = 61613;
my $STOMP_USER = 'admin';
my $STOMP_PASS = 'admin';
my $DESTINATION = '/topic/MyPerlTopic';
my $MESSAGES_COUNT = 10; # Количество сообщений
# --- Подключение ---
my $stomp = Net::STOMP::Client->new(
host => $STOMP_HOST,
port => $STOMP_PORT,
);
$stomp->connect(
login => $STOMP_USER,
passcode => $STOMP_PASS,
);
print "Sending $MESSAGES_COUNT messages to topic...\n";
# --- Цикл отправки ---
for my $i (1 .. $MESSAGES_COUNT) {
my $body = "Message #$i sent to topic at " . localtime(time);
$stomp->send(
destination => $DESTINATION,
body => $body,
'destination-type' => 'MULTICAST', # Для топиков (все подписчики получают)
'persistent' => 'true', # Сохранять сообщения на диск
'priority' => '4', # Приоритет от 0 до 9
'expires' => '0', # Бесконечное время жизни
'auto-delete' => 'false', # Не удалять тему автоматически
'JMSCorrelationID' => "msg-$i", # Идентификатор для отслеживания
'content-type' => 'text/plain', # Тип содержимого
);
print " Sent: $body\n";
sleep 0.5; # Небольшая пауза между отправками
}
print "[OK] All messages sent to topic\n";
# --- Отключение ---
$stomp->disconnect();
exit 0;
Заголовки (headers) и их назначение:
- destination-type: MULTICAST — ключевое отличие от очереди. Указывает Artemis, что сообщение адресовано топику (Multicast-семантика). Все подписчики этого топика получат копию сообщения.
- persistent: true — сообщение будет сохранено на диск для надежности.
- priority: 4 — приоритет сообщения (от 0 — низший, до 9 — высший).
- expires: 0 — сообщение не имеет срока годности (хранится бесконечно).
- auto-delete: false — предотвращает автоматическое удаление адреса топика, когда последний потребитель отписывается.
- JMSCorrelationID: "msg-$i" — уникальный идентификатор для каждого сообщения, который можно использовать для отслеживания корреляции между запросами и ответами.
- content-type: text/plain — явно указывает тип содержимого тела сообщения.
Consumer (получатель нескольких сообщений)
Создадим файл
consumer_loop.pl. Этот скрипт демонстрирует потребителя, который подписывается на топик и бесконечно слушает входящие сообщения. В отличие от очереди, каждый активный потребитель топика получит свою копию каждого отправленного сообщения.
#!/usr/bin/perl
use strict;
use warnings;
use Net::STOMP::Client;
# --- Конфигурация подключения ---
my $STOMP_HOST = 'localhost';
my $STOMP_PORT = 61613;
my $STOMP_USER = 'admin';
my $STOMP_PASS = 'admin';
my $DESTINATION = '/topic/MyPerlTopic';
# --- Подключение к брокеру ---
my $stomp = Net::STOMP::Client->new(
host => $STOMP_HOST,
port => $STOMP_PORT,
);
# --- Аутентификация ---
$stomp->connect(
login => $STOMP_USER,
passcode => $STOMP_PASS,
);
# --- Подписка на топик ---
$stomp->subscribe(
destination => $DESTINATION,
headers => {
'subscription-type' => 'MULTICAST',
'ack' => 'client',
},
);
print "[INFO] Listening for messages from '$DESTINATION' (Press Ctrl+C to stop)...\n";
# --- Получение нескольких сообщений ---
while (1) {
my $frame = $stomp->receive_frame();
if ($frame && $frame->command eq 'MESSAGE') {
my $body = $frame->body;
my $message_id = $frame->headers->{'message-id'} || 'unknown';
print "[RECEIVED] ID: $message_id, Body: $body\n";
# Получаем ID для подтверждения
my $ack_id = $frame->headers->{'ack'};
if ($ack_id) {
$stomp->ack(headers => { 'id' => $ack_id });
print "[ACK] Message $message_id acknowledged\n";
}
}
}
# --- Отключение ---
$stomp->disconnect();
Заголовки (headers) и их назначение:
- subscription-type: MULTICAST — указывает Artemis, что подписка осуществляется на топик (Multicast-семантика). Это гарантирует получение всех сообщений, отправленных в этот топик.
- ack: client — включает ручной режим подтверждения. Сообщение не будет удалено из топика (для durable-подписчиков), пока клиент явно не отправит ACK. Это дает гарантию, что сообщение обработано успешно.
Работа с SSL
Для начала создадим сертификаты для подписчика и сервера (create_certs.bat):
@echo off
if not exist ".\certs" mkdir certs
cd certs
REM 1. Корневой CA
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.cer -subj "/C=RU/ST=Moscow/L=Moscow/O=MyOrg/CN=Artemis CA"
REM 2. Сертификат сервера Artemis
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/C=RU/ST=Moscow/L=Moscow/O=MyOrg/CN=localhost"
openssl x509 -req -days 3650 -in server.csr -CA ca.cer -CAkey ca.key -set_serial 01 -out server.cer
REM 3. Упаковываем ключ и сертификат сервера в PKCS12 KeyStore ===
openssl pkcs12 -export -in server.cer -inkey server.key -out server.p12 -name "artemis" -passout pass:changeit
REM 4. Упаковываем CA в PKCS12 TrustStore (если требуется проверка клиентов) ===
openssl pkcs12 -export -nokeys -in ca.cer -out truststore.p12 -name "caroot" -passout pass:changeit
REM 5. Сертификат клиента (для Perl)
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/C=RU/ST=Moscow/L=Moscow/O=MyOrg/CN=perl-client"
openssl x509 -req -days 3650 -in client.csr -CA ca.cer -CAkey ca.key -set_serial 02 -out client.cer
echo Certificates and KeyStores have been created!
pause
В параметрах -subj указан CN=localhost. Это критично, потому что Perl-скрипт будет подключаться к localhost. Если вы укажете другое имя, проверка сертификата на стороне клиента завершится ошибкой. Аналогичный под linux (create_certs.sh):
#!/bin/bash
# Создаем директорию для сертификатов
if [ ! -d "./certs" ]; then
mkdir certs
fi
cd certs
# 1. Корневой CA
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.cer -subj "/C=RU/ST=Moscow/L=Moscow/O=MyOrg/CN=Artemis CA"
# 2. Сертификат сервера Artemis
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/C=RU/ST=Moscow/L=Moscow/O=MyOrg/CN=localhost"
openssl x509 -req -days 3650 -in server.csr -CA ca.cer -CAkey ca.key -set_serial 01 -out server.cer
# 3. Упаковываем ключ и сертификат сервера в PKCS12 KeyStore
openssl pkcs12 -export -in server.cer -inkey server.key -out server.p12 -name "artemis" -passout pass:changeit
# 4. Упаковываем CA в PKCS12 TrustStore (если требуется проверка клиентов)
openssl pkcs12 -export -nokeys -in ca.cer -out truststore.p12 -name "caroot" -passout pass:changeit
# 5. Сертификат клиента (для Perl)
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/C=RU/ST=Moscow/L=Moscow/O=MyOrg/CN=perl-client"
openssl x509 -req -days 3650 -in client.csr -CA ca.cer -CAkey ca.key -set_serial 02 -out client.cer
echo "Certificates and KeyStores have been created!"
Выполним один из файлов создания сертификатов. Изменим файл docker-compose.yml (первый вариант с копированием файлов в контейнер):
services:
artemis:
build:
context: .
dockerfile: Dockerfile
container_name: artemis
ports:
- "61613:61613"
- "61614:61614"
- "61616:61616"
- "8161:8161"
environment:
- ARTEMIS_USER=admin
- ARTEMIS_PASSWORD=admin
volumes:
- artemis-data:/var/lib/artemis/data
- artemis-logs:/var/lib/artemis/log
restart: unless-stopped
volumes:
artemis-data:
driver: local
artemis-logs:
driver: local
И сам Dockerfile:
FROM apache/activemq-artemis:latest
# Переключаемся на root для создания директорий
USER root
# Создаем папку для сертификатов
RUN mkdir -p /opt/artemis/etc/certs
# Копируем broker.xml
COPY broker.xml /var/lib/artemis-instance/etc-override/broker.xml
# Копируем сертификаты
COPY certs/ /opt/artemis/etc/certs/
# Меняем владельца (чтобы Artemis мог читать файлы)
RUN chown -R artemis:artemis /opt/artemis/etc/certs
RUN chmod 600 /opt/artemis/etc/certs/*.key
USER artemis
# Выводим содержимое для проверки (опционально)
RUN ls -la /opt/artemis/etc/certs/
Этот подход подходит для production-сред, где нужна самодостаточность образа. Для сборки образа и запуска:
docker-compose build --no-cache
docker-compose up -d
Второй вариант с монтированием файлов (Dockerfile не нужен):
services:
artemis:
image: apache/activemq-artemis:latest
container_name: artemis
ports:
- "61613:61613"
- "61614:61614"
- "61616:61616"
- "8161:8161"
environment:
- ARTEMIS_USER=admin
- ARTEMIS_PASSWORD=admin
volumes:
- artemis-data:/var/lib/artemis/data
- artemis-logs:/var/lib/artemis/log
- <ваш_путь_к_сертификатам>/certs:/opt/artemis/etc/certs:ro
- <ваш_путь_к_broker.xml>/broker.xml:/var/lib/artemis-instance/etc-override/broker.xml:ro
restart: unless-stopped
volumes:
artemis-data:
driver: local
artemis-logs:
driver: local
Этот подход подходит для разработки и сред, где сертификаты часто обновляются. Для запуска:
docker-compose up -d
broker.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
<core xmlns="urn:activemq:core">
<name>0.0.0.0</name>
<persistence-enabled>true</persistence-enabled>
<journal-type>ASYNCIO</journal-type>
<paging-directory>./data/paging</paging-directory>
<bindings-directory>./data/bindings</bindings-directory>
<journal-directory>./data/journal</journal-directory>
<large-messages-directory>./data/large-messages</large-messages-directory>
<journal-datasync>true</journal-datasync>
<journal-min-files>2</journal-min-files>
<journal-pool-files>10</journal-pool-files>
<journal-device-block-size>4096</journal-device-block-size>
<journal-file-size>10M</journal-file-size>
<journal-buffer-timeout>2000</journal-buffer-timeout>
<disk-scan-period>5000</disk-scan-period>
<max-disk-usage>90</max-disk-usage>
<critical-analyzer>true</critical-analyzer>
<critical-analyzer-timeout>120000</critical-analyzer-timeout>
<critical-analyzer-check-period>60000</critical-analyzer-check-period>
<critical-analyzer-policy>HALT</critical-analyzer-policy>
<global-max-size>100MB</global-max-size>
<acceptors>
<!-- STOMP без SSL -->
<acceptor name="stomp">tcp://0.0.0.0:61613?protocols=STOMP</acceptor>
<!-- STOMP с SSL -->
<acceptor name="stomp-ssl">tcp://0.0.0.0:61614?sslEnabled=true;keyStorePath=/opt/artemis/etc/certs/server.p12;keyStorePassword=changeit;keyStoreType=PKCS12;trustStorePath=/opt/artemis/etc/certs/truststore.p12;trustStorePassword=changeit;trustStoreType=PKCS12;enabledProtocols=TLSv1.2,TLSv1.3</acceptor>
<!-- Мультипротокольный -->
<acceptor name="all">tcp://0.0.0.0:61616?protocols=STOMP,AMQP,OPENWIRE</acceptor>
</acceptors>
<security-settings>
<security-setting match="#">
<permission type="createAddress" roles="admin,amq"/>
<permission type="deleteAddress" roles="admin,amq"/>
<permission type="createDurableQueue" roles="admin,amq"/>
<permission type="deleteDurableQueue" roles="admin,amq"/>
<permission type="createNonDurableQueue" roles="admin,amq"/>
<permission type="deleteNonDurableQueue" roles="admin,amq"/>
<permission type="send" roles="admin,amq"/>
<permission type="consume" roles="admin,amq"/>
<permission type="browse" roles="admin,amq"/>
<permission type="manage" roles="admin,amq"/>
</security-setting>
</security-settings>
<address-settings>
<address-setting match="#">
<dead-letter-address>DLQ</dead-letter-address>
<expiry-address>ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
<max-size-bytes>10485760</max-size-bytes>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
<address-full-policy>BLOCK</address-full-policy>
<auto-create-queues>true</auto-create-queues>
<auto-create-addresses>true</auto-create-addresses>
<auto-delete-queues>false</auto-delete-queues>
<auto-delete-addresses>false</auto-delete-addresses>
</address-setting>
</address-settings>
</core>
</configuration>
Краткое пояснение конфигурации broker.xml:
- Acceptor stomp-ssl (порт 61614):
- sslEnabled=true — включает защищённое SSL-соединение для STOMP-клиентов.
- keyStorePath=/opt/artemis/etc/certs/server.p12 — путь к хранилищу серверного сертификата (PKCS12) для аутентификации перед клиентами.
- trustStorePath=/opt/artemis/etc/certs/truststore.p12 — хранилище доверенных сертификатов для проверки клиентских сертификатов (взаимная аутентификация).
- enabledProtocols=TLSv1.2,TLSv1.3 — разрешены только современные версии TLS для безопасности.
- Acceptor stomp (порт 61613):
- Незащищённое соединение без SSL — используется для отладки или локальных окружений без требований к шифрованию.
- Acceptor all (порт 61616):
- Поддерживает одновременно STOMP, AMQP и OpenWire — универсальный порт для разнородных клиентов.
- Security-settings match="#":
- Правила безопасности для всех адресов (# — wildcard).
- Роли admin и amq имеют полный набор прав: создание/удаление очередей и адресов, отправка, потребление, просмотр и управление.
- Address-settings match="#":
- dead-letter-address: DLQ — недоставленные сообщения перенаправляются в очередь DLQ.
- expiry-address: ExpiryQueue — просроченные сообщения попадают в очередь ExpiryQueue.
- max-size-bytes: 10485760 (10 МБ) — максимальный размер адреса до применения политики BLOCK.
- address-full-policy: BLOCK — при заполнении адреса входящие сообщения блокируются (не теряются).
- auto-create-queues: true — очереди создаются автоматически при первом обращении (удобно для разработки).
- auto-delete-queues: false — очереди не удаляются автоматически, даже после отписки всех потребителей (сохраняются до ручного удаления).
Producer (отправитель SSL)
Создадим файл
producer_ssl.pl. Этот скрипт демонстрирует производителя, который отправляет одно JSON-сообщение в очередь (а не в топик) с использованием защищённого SSL-соединения. Он использует семантику ANYCAST для очередей, обеспечивая доставку сообщения в режиме "точка-точка" одному из активных потребителей. Скрипт настраивает взаимную аутентификацию через клиентские сертификаты и проверку подлинности сервера, гарантируя безопасную передачу данных. Сообщение содержит временную метку, идентификатор пользователя и текстовое поле, а также дополнительные STOMP-заголовки для управления приоритетом, персистентностью и типом контента. Процесс завершается корректным отключением от брокера после отправки.
#!/usr/bin/perl
use strict;
use warnings;
use Net::STOMP::Client;
use JSON;
use IO::Socket::SSL;
# --- Конфигурация ---
my $STOMP_HOST = 'localhost';
my $STOMP_PORT = 61614;
my $STOMP_USER = 'admin';
my $STOMP_PASS = 'admin';
my $DESTINATION = '/queue/MyQueueSSL';
# --- Пути к файлам сертификатов ---
my $CLIENT_CERT_FILE = '<ваш_путь_к_сертификатам>/certs/client.cer';
my $CLIENT_KEY_FILE = '<ваш_путь_к_сертификатам>/certs/client.key';
my $CA_CERT_FILE = '<ваш_путь_к_сертификатам>/certs/ca.cer';
# --- Подключение с SSL ---
my $stomp = Net::STOMP::Client->new(
host => $STOMP_HOST,
port => $STOMP_PORT,
sockopts => {
SSL_ca_file => $CA_CERT_FILE,
SSL_cert_file => $CLIENT_CERT_FILE,
SSL_key_file => $CLIENT_KEY_FILE,
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER,
SSL_version => 'TLSv1_2',
SSL_verifycn_name => 'localhost',
},
);
# --- Аутентификация ---
$stomp->connect(
login => $STOMP_USER,
passcode => $STOMP_PASS,
);
# --- Отправка JSON-сообщения ---
my $data = {
timestamp => time(),
user => 'perl-producer',
message => 'Hello Artemis with SSL!',
};
$stomp->send(
destination => $DESTINATION,
body => encode_json($data),
'destination-type' => 'ANYCAST', # Для очередей
'persistent' => 'true', # Постоянное сообщение
'priority' => '4', # Приоритет от 0 до 9
'expires' => '0', # Бесконечное время жизни
'content-type' => 'application/json',
);
print "JSON-message sent with SSL\n";
# --- Отключение ---
$stomp->disconnect();
exit 0;
Consumer (получатель нескольких сообщений SSL)
Создадим файл consumer_ssl.pl. Этот скрипт демонстрирует защищённого потребителя, который подписывается на очередь и бесконечно слушает входящие сообщения через SSL-соединение. В отличие от топика, очередь использует семантику ANYCAST, где каждое сообщение доставляется только одному из активных потребителей в режиме "точка-точка". Скрипт настраивает взаимную аутентификацию через сертификаты, использует ручное подтверждение (client-ack) для гарантированной доставки и автоматически декодирует JSON-сообщения, выводя их структуру через Data::Dumper. Потребитель работает в бесконечном цикле, обрабатывая входящие фреймы, подтверждая получение каждого сообщения и корректно обрабатывая возможные ошибки парсинга JSON.
#!/usr/bin/perl
use strict;
use warnings;
use Net::STOMP::Client;
use JSON;
use Data::Dumper;
use IO::Socket::SSL;
# --- Конфигурация подключения ---
my $STOMP_HOST = 'localhost';
my $STOMP_PORT = 61614;
my $STOMP_USER = 'admin';
my $STOMP_PASS = 'admin';
my $DESTINATION = '/queue/MyQueueSSL';
# --- Пути к сертификатам ---
my $CLIENT_CERT_FILE = '<ваш_путь_к_сертификатам>/certs/client.cer';
my $CLIENT_KEY_FILE = '<ваш_путь_к_сертификатам>/certs/client.key';
my $CA_CERT_FILE = '<ваш_путь_к_сертификатам>/certs/ca.cer';
# --- Подключение к брокеру с SSL ---
my $stomp = Net::STOMP::Client->new(
host => $STOMP_HOST,
port => $STOMP_PORT,
sockopts => {
SSL_ca_file => $CA_CERT_FILE,
SSL_cert_file => $CLIENT_CERT_FILE,
SSL_key_file => $CLIENT_KEY_FILE,
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER,
SSL_version => 'TLSv1_2',
SSL_verifycn_name => 'localhost',
# Для отладки:
# SSL_debug => 1,
},
);
# --- Аутентификация ---
$stomp->connect(
login => $STOMP_USER,
passcode => $STOMP_PASS,
);
# --- Подписка ---
$stomp->subscribe(
destination => $DESTINATION,
'subscription-type' => 'ANYCAST', # Для очередей
'ack' => 'client', # Ручное подтверждение
);
print "[INFO] Listening for messages on SSL port $STOMP_PORT from '$DESTINATION' (Press Ctrl+C to stop)...\n";
# --- Получение нескольких сообщений ---
while (1) {
my $frame = $stomp->receive_frame();
if ($frame && $frame->command eq 'MESSAGE') {
my $body = $frame->body;
my $message_id = $frame->headers->{'message-id'} || 'unknown';
my $content_type = $frame->headers->{'content-type'} || 'text/plain';
if ($content_type eq 'application/json') {
eval {
my $data = decode_json($body);
print "[JSON] ";
print Dumper($data);
};
if ($@) {
print "[ERROR] Invalid JSON: $@\n";
print "[RAW] $body\n";
}
} else {
print "[TEXT] $body\n";
}
# Получаем ID для подтверждения
my $ack_id = $frame->headers->{'ack'};
if ($ack_id) {
eval { $stomp->ack('id' => $ack_id) };
if ($@) {
print "[WARNING] ACK failed: $@\n";
} else {
print "[ACK] Message acknowledged (ID: $ack_id)\n";
}
}
}
}
# --- Отключение ---
$stomp->disconnect();
Итого
Мы рассмотрели три варианта docker-compose.yml для развертывания ArtemisMQ в зависимости от потребностей окружения:
- Базовый — запуск официального образа с минимальной настройкой для быстрого старта.
- SSL (сборка образа) — использование Dockerfile для копирования сертификатов и переопределённого broker.xml внутрь контейнера. Подходит для production-сред, где важна самодостаточность образа.
- SSL (монтирование томов) — подключение сертификатов и конфигурации через volumes без пересборки образа. Удобно для разработки и частого обновления сертификатов.
Все варианты запускаются одной командой docker-compose up -d, не требуя сложной ручной установки брокера.
Использование портов (61613 для STOMP без шифрования, 61614 для защищённого STOMP через SSL, 61616 для мультипротокольных подключений и 8161 для веб-консоли) обеспечивает гибкость при разработке приложений с различными протоколами, безопасную передачу данных и удобный мониторинг через встроенный веб-интерфейс.
Примеры на Perl с использованием библиотеки Net::STOMP::Client демонстрируют базовые, но рабочие шаблоны для создания Producer (отправителя) и Consumer (получателя) как для очередей (Anycast), так и для топиков (Multicast), с поддержкой ручного подтверждения и SSL-шифрования для безопасного обмена сообщениями.