MQRC_UNKNOWN_ALIAS_BASE_Q при подключении к кластеру IBM MQ с использованием CCDT и Spring Boot JMSTemplate

У меня есть приложение Spring Boot, использующее JMSListener + IBMConnectionFactory + CCDT для подключения кластера IBM MQ.

Задайте следующие свойства подключения: - URL-адрес, указывающий на сгенерированный файл ccdt - имя пользователя (пароль не требуется, поскольку тестовая среда) - имя диспетчера очереди НЕ определено - поскольку это задача кластера, и несколько результатов Google, включая несколько stackoverflow они указывают, что в моем случае qmgr должен быть установлен на пустую строку.

Когда мой Spring Boot JMSListener пытается подключиться к очереди, возникает следующая ошибка MQRC_UNKNOWN_ALIAS_BASE_Q:

2019-01-29 11:05:00.329 WARN  [thread:DefaultMessageListenerContainer-44][class:org.springframework.jms.listener.DefaultMessageListenerContainer:892] - Setup of JMS message listener invoker failed for destination 'MY.Q.ALIAS' - trying to recover. Cause: JMSWMQ2008: Failed to open MQ queue 'MY.Q.ALIAS'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2082' ('MQRC_UNKNOWN_ALIAS_BASE_Q').
com.ibm.msg.client.jms.DetailedInvalidDestinationException: JMSWMQ2008: Failed to open MQ queue 'MY.Q.ALIAS'.
        at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:513)
        at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:215)

В журнале ошибок MQ я вижу следующее:

01/29/2019 03:08:05 PM - Process(27185.478) User(mqm) Program(amqrmppa)
                    Host(myhost) Installation(Installation1)
                    VRMF(9.0.0.5) QMgr(MyQMGR)

AMQ9999: Channel 'MyCHL' to host 'MyIP' ended abnormally.

EXPLANATION:
The channel program running under process ID 27185 for channel 'MyCHL'
ended abnormally. The host name is 'MyIP'; in some cases the host name
cannot be determined and so is shown as '????'.
ACTION:
Look at previous error messages for the channel program in the error logs to
determine the cause of the failure. Note that this message can be excluded
completely or suppressed by tuning the "ExcludeMessage" or "SuppressMessage"
attributes under the "QMErrorLog" stanza in qm.ini. Further information can be
found in the System Administration Guide.
----- amqrmrsa.c : 938 --------------------------------------------------------
01/29/2019 03:15:14 PM - Process(27185.498) User(mqm) Program(amqrmppa)
                    Host(myhost) Installation(Installation1)
                    VRMF(9.0.0.5) QMgr(MyQMGR)

AMQ9209: Connection to host 'MyIP' for channel 'MyCHL' closed.

EXPLANATION:
An error occurred receiving data from 'MyIP' over TCP/IP.  The connection
to the remote host has unexpectedly terminated.

The channel name is 'MyCHL'; in some cases it cannot be determined and so
is shown as '????'.
ACTION:
Tell the systems administrator.

Поскольку журнал ошибок MQ содержит QMgr (MyQMGR), значение MyQMGR, которое я не установил в свойствах соединения, я предполагаю, что маршрутизация будь в порядке: кластер MQ нашел qmgr для использования.

Псевдоним существует и указывает на существующий q. Бот целевой q и псевдоним добавляются в кластер с помощью команды CLUSTER (clustname).

Что может быть не так?


person Kumite    schedule 29.01.2019    source источник


Ответы (1)


Короткий ответ

  • Кластеризация MQ не используется приложением-потребителем для поиска очереди, из которой можно получить сообщения.
  • Кластеризация MQ используется, когда приложение-производитель отправляет сообщения, чтобы направить их к месту назначения.

дальнейшее чтение

Кластеризация используется при отправке сообщений, чтобы помочь обеспечить балансировку нагрузки для нескольких экземпляров кластеризованной очереди. В некоторых случаях люди используют это для горячего / холодного переключения при отказе, имея два экземпляра очереди и сохраняя только один PUT(ENABLED).

Если приложение является производителем, который помещает сообщения в кластеризованную очередь, ему нужно только быть подключенным к диспетчеру очередей в кластере и иметь разрешения для помещения в эту кластеризованную очередь. MQ, основанный на нескольких разных вещах, будет обрабатывать, куда отправить это сообщение.


До версии 7.1 было только два способа предоставить доступ к удаленным кластерным очередям:

  1. Используя QALIAS:

    • Определите локальный QALIAS, для которого в качестве TARGET установлено имя кластеризованной очереди.

      Обратите внимание, этот QALIAS сам по себе не нуждается в кластеризации.

    • Даю разрешение поставить на локальный QALIAS.
  2. Предоставьте разрешения для PUT в SYSTEM.CLUSTER.TRANSMIT.QUEUE.

Первый вариант позволяет предоставить детальный доступ приложению для определенных кластерных очередей в кластере. Второй вариант позволяет приложению помещать в любую кластерную очередь в кластере или любую очередь в любом кластерном диспетчере очередей в кластере.

В версии 7.1 IBM добавила новое необязательное поведение, которое было предоставлено параметром ClusterQueueAccessControl=RQMName в разделе Security раздела qm.ini. Если он включен (не по умолчанию), то вы можете предоставить приложению разрешение PUT на удаленные кластерные очереди напрямую, без необходимости в локальном QALIAS.


Кластеризация не для использования таких приложений, как ваш пример JMSListener.

Приложение, которое будет использовать любой QLOCAL (кластерный или нет), должно быть подключено к администратору очередей, в котором определен QLOCAL.

Если у вас есть ситуация, когда есть несколько экземпляров кластеризованного QLOCAL, которые PUT(ENABLED), вам необходимо убедиться, что у вас есть потребители, подключенные напрямую к каждому диспетчеру очередей, на котором размещен экземпляр.


Основываясь на вашем комментарии, у вас есть CCDT с такой записью, как:

CHANNEL('MyCHL') CHLTYPE(CLNTCONN) QMNAME('MyQMGR') CONNAME('node1url(port1),node2url(port2)')

Если есть два разных администратора очередей с разными именами, которые слушают node1url(port1) и node2url(port2), то у вас есть разные способы сделать это со стороны приложения.

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

  1. Если вы укажете *MyQMGR, он найдет канал или каналы с QMNAME('MyQMGR'), выберет один и подключится, и не будет требовать совпадения имени удаленного администратора очередей.
  2. Если в вашей CCDT у вас есть QNAME(''), для него установлено значение NULL, тогда в вашем приложении вы можете указать пустое имя диспетчера очередей или только пробел, и он найдет эту запись в CCDT и не будет требовать, чтобы имя удаленного диспетчера очереди совпадение.
  3. В своем приложении вы указываете имя администратора очередей как *, MQ будет использовать любой канал в CCDT и не будет обеспечивать соответствие имени удаленного администратора очередей.

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

Когда вы подключаетесь, вы попадаете в запись с двумя CONNAME и подключаетесь к первому IP(port), вы получите доступ ко второму IP(port), только если во время подключения первая недоступна, MQ попробует второй, или если вы подключены и у вас есть RECONNECT включен, а затем отключается первый MQ будет пытаться подключиться к первому, а затем ко второму.

Если вы хотите иметь обе кластерные очереди PUT(ENABLED) для приема трафика, тогда вы хотите иметь возможность специально подключаться к каждому из двух администраторов очередей для чтения этих очередей.

Я бы посоветовал вам добавить новый канал в каждый диспетчер очередей с другим специфическим именем QM, которое также отличается от существующего имени, примерно так:

CHANNEL('MyCHL1') CHLTYPE(CLNTCONN) QMNAME('MyQMGR1') CONNAME('node1url(port1)')
CHANNEL('MyCHL2') CHLTYPE(CLNTCONN) QMNAME('MyQMGR2') CONNAME('node2url(port2)')

Это будет в дополнение к существующей записи.

Для ваших компонентов размещения вы можете продолжать использовать канал, который может подключаться к любому администратору очередей.

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

person JoshMc    schedule 29.01.2019
comment
Большое спасибо! Примечание: JMSListener Spring мог выполнять GET через соединение CCDT, но он получал сообщения только от узла, который был указан на первом месте в конфигурации ccdt, поэтому GET не работает в кластере. - person Kumite; 07.02.2019
comment
Как выглядит ваша CCDT? - person JoshMc; 07.02.2019
comment
Поскольку большинство частей не читаются человеком, основная запись: имя канала (которое совпадает с именем соединения с сервером, которое я использовал для подключения в режиме клиента + пользовательский), за которым следуют два адреса: node1url (порт1), node2url (порт2). в случае кластерного / cdt GET мое приложение всегда получало сообщения на node1url (port1), но не на node2url (port2) - person Kumite; 08.02.2019
comment
Привет, Кумитэ, если у вас v8 / v9, вы можете использовать runmqsc -n для отображения CCDT следующим образом: echo "DIS CHL(*) QMNAME CONNAME" | MQCHLLIB=PATH/OF/CCDT MQCHLTAB=NAME_OF_CCDT runmqsc -n - person JoshMc; 08.02.2019
comment
Добавляю дополнительную информацию к моему ответу. - person JoshMc; 08.02.2019