Статьи

Изнутри кода: сетевые мосты ActiveMQ и подписки перенаправления спроса

Ранее я писал о сетевых соединителях ActiveMQ как способ помочь описать некоторые обязанности классов, которые связаны с настройкой сети посредников для ActiveMQ . Недавно мне пришлось погрузиться в этот раздел кода и найти, что сообщение в блоге неоценимо, чтобы помочь вспомнить вещи о сетевых разъемах, которые я бы не сохранил в памяти. Поскольку это было очень полезно для меня, я хотел бы продолжить с тем, как работают сетевые мосты и подписки на переадресацию по требованию.

Надеемся, что эта информация будет полезна для других, которые заинтересованы в получении дополнительной информации о том, что происходит под прикрытием, или для тех, кто участвует в проекте ActiveMQ и собирается покопаться в этой области кода.

Эта запись держит его ближе к деталям кода. Если вы заинтересованы в просмотре этого с более высокого уровня, у моего коллеги Якуба Кораба есть отличный пост с отличными диаграммами, которые объясняют брокерские сети.

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

<networkConnector uri="static://(tcp://localhost:61626,tcp://localhost:61627)" />

DiscoveryAgent, связанный с NetworkConnector, инициирует настройку моста для каждого транспортного URI, указанного в атрибуте uri networkConnector. Это означает, что если вы ожидаете, что несколько URI будут действовать как главные / подчиненные URI, тогда соединитель попытается установить мост. как хозяину, так и рабу всегда . Скорее всего, это не то, что вы хотите (т.е. вы хотите подключиться только к мастеру). Альтернативой было бы заключить URI в master-slave: транспорт, чтобы правильно идентифицировать URI и сначала подключиться к ведущему и только к ведомому в случае сбоя master.

Обратите внимание, что для каждого URI, если мост заканчивается разрушением из-за непредвиденного исключения, мост всегда будет пытаться воссоздать.

Что делает сетевой мост?

Так что же делает мост? Итак, сетевой мост в основном координирует свои действия с локальным посредником (используя VMTransport) и удаленным посредником (используя транспорт, указанный в URI: TCP / SSL / HTTP и т. Д.) И реализует поведение «переадресации спроса», ожидаемое от сети брокеры. Давайте посмотрим шаг за шагом, как это происходит.

Как работает мост

В методе DiscoveryNetworkConnector # onServiceAdd вы можете четко видеть, где создаются транспорты. Один для локального брокера и один для удаленного брокера. Далее вы увидите созданный мост, проходящий через транспорты, и, наконец, мост начался.

Когда мост запускается, он сначала настраивает TransportListener как для локальных, так и для удаленных транспортов, прежде чем запускать транспорты. Это позволяет мосту обслуживать команды от локальных и удаленных брокеров и действовать соответственно. Это своего рода то, что класс TransportConnection делает для обычных клиентов брокера. Основная часть кода для сетевых мостов находится в org.apache.activemq.network.DemandForwardingBridgeSupport.java. Поэтому, когда наши транспорты используют сообщения, отправляют сообщения или подтверждают сообщения, они делают это, используя объекты команды ActiveMQ напрямую.

После настройки прослушивателей запускаются транспорты (созданные в DiscoveryNetworkConnector # onServiceAdd), что запускает нормальный обмен объектами команд: для удаленного посредника происходит согласование проводного формата, чтобы определить, какая версия Использовать OpenWire (для соединений TCP / SSL), а затем удаленный посредник отправляет команду BrokerInfo удаленному транспортному мосту для идентификации себя. Для местного транспорта нет согласования проводного формата. Локальный посредник отправляет команду BrokerInfo локальному транспорту, чтобы идентифицировать себя.

Теперь у нас есть транспорты, настроенные на прослушивание входящих команд, и мы запустили их и общались с соответствующими брокерами (локальными и удаленными). Теперь ключ к перенаправлению спроса имеет место. Запускаем мост к удаленному брокеру. Эта часть отвечает за определение «спроса» со стороны других брокеров. У Гари Талли есть отличная запись в блогео точной терминологии Bridge, Demand и Forwarding, которая объясняет простым языком роль каждого из компонентов. Когда потребитель в удаленном брокере подписывается на пункт назначения, который существует у нашего локального брокера, мы считаем, что у этого потребителя есть «спрос» на сообщения в месте назначения нашего локального брокера. Например, рассмотрим локального посредника, подключенного к удаленному посреднику: если у меня есть производитель к месту назначения с именем «foo» на локальном посреднике, а потребитель подключается к удаленному посреднику и хочет установить подписку на место назначения с именем «foo» Удаленный брокер сделает это без беспокойства. Но на удаленном брокере нет производителей, которые бы «foo», а только один на локальном брокере. Когда мост настроен, он увидит, что существует удаленный запрос (потребитель) для сообщений на «foo», поэтому он будетпересылать сообщения для адресата «foo» удаленному брокеру. Там у нас есть «спрос» (потребитель на удаленном брокере) и переадресация сообщения таким образом: Переадресация спроса.

Так как же местный брокер определяет спрос?

В DemandForwardingBridgeSupport # startRemoteBridge мы устанавливаем соединение, сеанс и приемник для удаленного посредника. Потребитель настроен на использование из консультативной темы с именем ActiveMQ.Advisory.Consumer на удаленном посреднике. Если networkConnector настроен для моста временных адресатов, то потребитель также собирается прослушивать консультативные темы с именами ActiveMQ.Advisory.TempQueue и ActiveMQ.Advisory.TempQueue. Эти темы уведомляют слушателей о новых потребителях, которые устанавливают подписку на пункт назначения на удаленном посреднике.

Настройка спроса

Итак, теперь мы видим, что мост нашего локального брокера слушает консультативные темы по удаленному брокеру. Но как устроен «спрос»?

Когда мы получаем консультативное сообщение от удаленного брокера, мы проверяем, какая команда была основной причиной консультативного сообщения. Если основной причиной была ConsumerInfo (потребительская подписка), то мы знаем, что потребитель на удаленном брокере заинтересован в переадресации сообщений на него, поэтому мы настроили «подписку по требованию».

Пересылка сообщений

Происходит то, что та же команда ConsumerInfo, которая использовалась для создания подписки на удаленном посреднике, немного изменяется (с учетом нового идентификатора потребителя, сеанса и т. Д.) И передается локальному посреднику. Это создает соответствующую подписку на локального брокера для указанного пункта назначения. Теперь, когда сообщения отправляются в пункт назначения на локальном посреднике, локальный пункт назначения будет иметь подписку. Локальный посредник отправит сообщение в подписку (которая фактически является мостом, создавшим подписку), и теперь мост направит его удаленному посреднику. Вы можете видеть, как мост пересылает сообщение от локального посредника удаленному посреднику в DemandForwardingBridgeSupport # serviceLocalCommand в условии, которое проверяет, что это MessageDispatch.

DemandSubscription, поддерживаемая объектами-мостами, всегда будет соответствовать подписке на локальном посреднике и подписке на удаленном посреднике. Важным ключом к объектам DemandSubscription являются идентификаторы потребителей. LocalInfo ссылается на потребителя с customerId, связанным с подпиской на локальном посреднике. Параметр remoteInfo будет ссылаться на получателя с идентификатором потребителя, связанным с подпиской на удаленном посреднике.

Таковы основы. Я мог бы написать больше о различных вещах, которые появляются в разных конфигурациях, дуплексных мостах, более сложных сетях и т. Д., И т. Д., Но я думаю, что этого достаточно, чтобы позже пробежаться по моей памяти или помочь другим понять, как работает переадресация спроса. , Кроме того, я уже потратил достаточно времени на написание, теперь пришло время взломать Apollo JIRA.

Если у вас есть конкретные вопросы, пожалуйста, дайте мне знать!