Дублирование сообщений с профилями и привязками оборудования для нескольких агентов HARD
Задача
В отдельных сегментах сети оператора используются различные схемы доступа и работают независимо друг от друга отдельные DHCP- и RADIUS-серверы. На каждом сервере установлен отдельный экземпляр агента HARD с отдельным кэшем в MongoDB. Необходимо обеспечить получение каждым агентом HARD сообщений из двух общих очередей провижининга.
Решение
Сообщения, получаемые ActiveMQ из очередей провижининга (Oracle AQ), распространяются в режиме мультикаста по нескольким собственным очередям. Каждый агент HARD работает со своей ActiveMQ-очередью и получает свою копию сообщения из провижининга.
... <camelContext xmlns="http://camel.apache.org/schema/spring" id="camel"> ... <route> <from uri="oracleTopic:topic:AIS_NET.HP_PROFILES_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> <multicast stopOnException="true"> <to uri="activemq:queue:hydra_profiles_pppoe-rad"/> <!-- Equipment profiles for HARD agent at PPPoE RADIUS-server --> <to uri="activemq:queue:hydra_profiles_ran-dhcp"/> <!-- Equipment profiles for HARD agent at Radio Access Network DHCP-server --> <to uri="activemq:queue:hydra_profiles_ran-rad"/> <!-- Equipment profiles for HARD agent at Radio Access Network RADIUS-server --> </multicast> </route> <route> <from uri="oracleTopic:topic:AIS_NET.HP_EQUIPMENT_BINDS_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> <multicast stopOnException="true"> <to uri="activemq:queue:hydra_equipment_binds_pppoe-rad"/> <!-- Equipment binds for HARD agent at PPPoE RADIUS-server --> <to uri="activemq:queue:hydra_equipment_binds_ran-dhcp"/> <!-- Equipment binds for HARD agent at Radio Access Network DHCP-server --> <to uri="activemq:queue:hydra_equipment_binds_ran-rad"/> <!-- Equipment binds for HARD agent at Radio Access Network RADIUS-server --> </multicast> </route> ... </camelContext> ...
... # Настройки подключения к ActiveMQ syncer: stomp: # Адрес host: '192.168.123.45' # Порт port: 61613 # Имя пользователя login: 'hydra' # Пароль пользователя password: 'Change me please' queues: # Наименование очереди с профилями profiles: 'hydra_profiles_pppoe-rad' # Наименование очереди с привязками binds: 'hydra_equipment_binds_pppoe-rad' ...
... # Настройки подключения к ActiveMQ syncer: stomp: # Адрес host: '192.168.123.45' # Порт port: 61613 # Имя пользователя login: 'hydra' # Пароль пользователя password: 'Change me please' queues: # Наименование очереди с профилями profiles: 'hydra_profiles_ran-rad' # Наименование очереди с привязками binds: 'hydra_equipment_binds_ran-rad' ...
Помещение команд с вызовом определённого скрипта в отдельную очередь
Задача
Один из используемых для провижининга оборудования скриптов работает очень медленно: например он управляет портами коммутаторов доступа по SNMP и часто отправляет команды повторно из-за отсутствия ответа коммутаторов при одной попытке. Так как очередь используется общая, команды с данным скриптом могут «тормозить» при большой нагрузке выполнение «быстрых» команд управления сессиями на BRAS'е. Необходимо отделить обработку проблемных команд от основного потока.
Решение
Сообщения с медленными командами выделяются брокером в отдельную очередь для агента HEX — обрабатываются данные сообщения независимо от остальных.
... <camelContext xmlns="http://camel.apache.org/schema/spring" id="camel"> ... <route> <from uri="oracleTopic:topic:AIS_NET.HP_COMMANDS_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> <choice> <when> <xpath>count(/command/vc_command[contains(.,'/opt/hydra/scripts/reset-switch-port.sh')]) > 0</xpath> <to uri="activemq:queue:hydra_commands_reset-switch-port"/> </when> <otherwise> <to uri="activemq:queue:hydra_commands"/> </otherwise> </choice> </route> <route> <from uri="activemq:queue:hydra_command_results"/> <to uri="oracleTopic:topic:AIS_NET.HP_COM_RES_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> </route> ... </camelContext> ...
... hydra: command_queues: # <Очередь для приёма команд>: <Очередь для отправки результата> - 'hydra_commands': 'hydra_command_results' - 'hydra_commands_reset-switch-port': 'hydra_command_results' ...
Обновление до версии 6.3+
vc_command теперь содержит значение, закодированное в Base64. В сязи с этим команду для сравнения в xpath также нужно закодировать, например так:
echo -n "your_command" | base64
Полученный результат использовать при выборе маршрутизации <xpath>count(/command/vc_command[contains(.,'your_command_in_base64')]) > 0</xpath>
Если команда может иметь различные вариации, то необходимо выделить общую часть
Команда в UTF-8 | Команда в Base64 |
---|---|
prev-ip-addr: next-ip-addr: 192.168.0.1 | cHJldi1pcC1hZGRyOiAgbmV4dC1pcC1hZGRyOiAxOTIuMTY4LjAuMQ== |
prev-ip-addr: next-ip-addr: 192.168.0.2 | cHJldi1pcC1hZGRyOiAgbmV4dC1pcC1hZGRyOiAxOTIuMTY4LjAuMg== |
prev-ip-addr: 192.168.0.1 next-ip-addr: | cHJldi1pcC1hZGRyOiAxOTIuMTY4LjAuMSBuZXh0LWlwLWFkZHI6IA== |
prev-ip-addr: 192.168.0.2 next-ip-addr: | cHJldi1pcC1hZGRyOiAxOTIuMTY4LjAuMiBuZXh0LWlwLWFkZHI6IA== |
prev-ip-addr: | cHJldi1pcC1hZGRyOg== |
В данном примере можно выделить общую часть команды в Base64 — cHJldi1pcC1hZGRyO, которую и нужно использовать при маршрутизации.
Безусловное автоматическое удаление сообщений из очередей
Задача
Провижининг используется только для формирования команд по конфигурациям. RADIUS-взаимодействия нет — агент HARD не установлен. Сообщения с профилями и привязками оборудования накапливаются в очередях Oracle, напрасно занимая бесценное место в табличных пространствах.
Бизнес-хуки Гидры не используются. Сообщения копятся в очереди Oracle, занимая место в табличных пространствах
Решение
Настроить в AcitveMQ получение этих сообщений, но без сохранения их в самом брокере. Для этого в конфигурации ActiveMQ можно использовать директиву <stop/>
, прерывающую маршрутизацию:
... <camelContext xmlns="http://camel.apache.org/schema/spring" id="camel"> <!-- Очередь команд провижининга AQ_BI_HYDRA_COMMANDS --> <route> <from uri="oracleTopic:topic:AIS_NET.HP_COMMANDS_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> <to uri="activemq:queue:hydra_commands_1"/> </route> <!-- Очередь результатов выполнения команд провижининга AQ_BI_HYDRA_COM_RES --> <route> <from uri="activemq:queue:hydra_command_results_1"/> <to uri="oracleTopic:topic:AIS_NET.HP_COM_RES_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> </route> <!-- Очередь профилей AQ_BI_HYDRA_PROFILES --> <route> <from uri="oracleTopic:topic:AIS_NET.HP_PROFILES_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> <stop/> <to uri="activemq:queue:hydra_profiles_1"/> </route> <!-- Очередь привязок оборудования AQ_BI_HYDRA_EQUIP_BINDS --> <route> <from uri="oracleTopic:topic:AIS_NET.HP_EQUIPMENT_BINDS_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> <stop/> <to uri="activemq:queue:hydra_equipment_binds_1"/> </route> <!-- Очередь сообщений бизнес-хуков AQ_BI_HYDRA_MESSAGES --> <route> <from uri="oracleTopic:topic:AIS_NET.HYDRA_MESSAGES?clientId=ActiveMQ&durableSubscriptionName=HP"/> <stop/> </route> </camelContext> ...
Директиву to
из маршрута удалять не стоит: при необходимости «включения» достаточно будет закомментировать или удалить строку с stop
.
После этого все сообщения из очереди Oracle будут разбираться и удаляться исходя из RETENTION
в ALL_QUEUES
.
Входящая системная очередь
Задача
Гидра поддерживает механизм перевыполнения команд при записи сообщений определенного формата во входящую системную очередь (см. Запрос текущего состояния). Для записи этих сообщений в очередь удобно использовать ActiveMQ в качестве прокси, который поддерживает множество различных протоколов (STOMP, AMPQ, REST), вместо использования оракловых процедур
Решение
Настроить в AcitveMQ получение этих сообщений с отправкой в системную очередь:
... <camelContext xmlns="http://camel.apache.org/schema/spring" id="camel"> <route> <from uri="activemq:queue:hydra_input_messages_1"/> <to uri="oracleTopic:topic:AIS_NET.HB_SYS_IN_1?clientId=ActiveMQ&durableSubscriptionName=HB"/> </route> </camelContext> ...
Выдать права для пользователя AIS_PROVISIONING для записи сообщений в системную очередь:
BEGIN DBMS_AQADM.GRANT_QUEUE_PRIVILEGE( privilege => 'enqueue', queue_name => 'AIS_NET.HB_SYS_IN_1', grantee => 'AIS_PROVISIONING'); END;
Теперь можно отправлять сообщения в ActiveMQ. Например, можно использовать для этой цели REST API:
echo -n "body=<system_message> <vc_message_type>ProvisioningCurrentStateRequest</vc_message_type> <n_firm_id>100</n_firm_id> <content> <vc_key>Shaper-IP</vc_key> <vc_value>127.0.0.1</vc_value> <n_value /> <d_value /> </content> </system_message>" | curl -u admin:admin --data-binary '@-' "http://192.168.1.1:8161/api/message/hydra_input_messages_1?type=queue"
Где Shaper-IP
- название атрибута шаблона операторского профиля (IP-адрес шейпера), 127.0.0.1
- его значение, 192.168.1.1
- IP-адрес ActiveMQ.
Ускорение работы ActiveMQ
Задача
В базе сделана переотправка профилей, но ActiveMQ слишком медленно забирает сообщения из базы. Нужно ускорить работу ActiveMQ
Решение
Мы настраиваем курсор, это делается в конфиге activemq.xml
... <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}" useJmx="false" advisorySupport="false"> <!-- Use VM cursor For more information, see: http://activemq.apache.org/message-cursors.html --> <destinationPolicy> <policyMap> <policyEntries> <policyEntry topic=">" producerFlowControl="true" memoryLimit="1000mb"> <pendingSubscriberPolicy> <vmCursor /> </pendingSubscriberPolicy> </policyEntry> <policyEntry queue=">" producerFlowControl="true" memoryLimit="1000mb"> <pendingQueuePolicy> <vmQueueCursor/> </pendingQueuePolicy> </policyEntry> </policyEntries> </policyMap> </destinationPolicy> ...
Старые настройки можно убрать
... <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}"> <destinationPolicy> <policyMap> <policyEntries> <policyEntry topic=">" > <!-- The constantPendingMessageLimitStrategy is used to prevent slow topic consumers to block producers and affect other consumers by limiting the number of messages that are retained For more information, see: http://activemq.apache.org/slow-consumer-handling.html --> <pendingMessageLimitStrategy> <constantPendingMessageLimitStrategy limit="1000"/> </pendingMessageLimitStrategy> </policyEntry> </policyEntries> </policyMap> </destinationPolicy> ...
Задача
Скопилась большая очередь результатов команд, ActiveMQ медленно переносит сообщения в очередь Oracle.
Решение
При отправке сообщений в очередь Oracle, ActiveMQ завершает сессию после каждого переданного сообщения. Чтобы изменить такое поведение, настроим использование пула соединений к Oracle.
Изменим URI для очереди Oracle:
... <route> <from uri="activemq:queue:hydra_command_results_1"/> <to uri="oraclePool:topic:AIS_NET.HP_COM_RES_1?clientId=ActiveMQ&durableSubscriptionName=HP"/> </route> ...
И добавим описание PooledConnectionFactory после описания oracleTopic:
... <bean id="oracleTopic" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory" ref="oracleTopicCredentials"/> </bean> <bean id="jmsPooledConnectionFactory" class="org.apache.activemq.jms.pool.PooledConnectionFactory" init-method="start" destroy-method="stop" > <property name="maxConnections" value="7" /> <property name="connectionFactory" ref="oracleTopicCredentials" /> </bean> <bean id="oraclePool" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory" ref="jmsPooledConnectionFactory"/> </bean> ...