IBM MQ MQCONN от хоста к контейнеру Docker

#c #docker #ibm-mq

#c #docker #ibm-mq

Вопрос:

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

Ниже приведен клиентский код, взятый из примера IBM. Вопрос в том, какой протокол используется, когда вызывается MQCONN, поскольку IP / порт не указан? Я могу только догадываться, что это какой-то IPC. По этой причине я запускаю контейнер docker с параметром —ipc=»host», но он по-прежнему терпит неудачу с CompCode=2, Reason=2058

 #include <cmqc.h>static char Parm1[MQ_Q_MGR_NAME_LENGTH] ;
⋮
int  main(int argc, char *argv[] )
   {
   /*                                                    */
   /*     Variables for MQ calls                         */
   /*                                                    */
   MQHCONN Hconn;      /* Connection handle              */
   MQLONG  CompCode;   /* Completion code                */
   MQLONG  Reason;     /* Qualifying reason              *//* Copy the queue manager name, passed in the         */
   /* parm field, to Parm1                               */
   strncpy(Parm1,argv[1],MQ_Q_MGR_NAME_LENGTH);
⋮
   /*                                                    */
   /* Connect to the specified queue manager.            */
   /*   Test the output of the connect call.  If the     */
   /*   call fails, print an error message showing the   */
   /*   completion code and reason code, then leave the  */
   /*   program.                                         */
   /*                                                    */
   MQCONN(Parm1,
          amp;Hconn,
          amp;CompCode,
          amp;Reason);
   if ((CompCode != MQCC_OK) | (Reason != MQRC_NONE))
      {
      sprintf(pBuff, MESSAGE_4_E,
              ERROR_IN_MQCONN, CompCode, Reason);
      PrintLine(pBuff);
      RetCode = CSQ4_ERROR;
      goto AbnormalExit2;
      }
⋮
   }
  

Комментарии:

1. Если клиентское приложение выполняется локально на том же сервере, что и диспетчер очередей, оно может подключаться в режиме «привязки», используя только общую память. Если клиент MQ не является локальным, и вы вызываете MQCONN с именем диспетчера очередей, он попытается выяснить, как подключиться к нему с помощью нескольких различных методов, включая переменные среды или mqclient.ini. Если ничего из этого не найдено, обычно выдается ошибка 2058 (MQRC_Q_MGR_NAME_ERROR). С помощью docker вам потребуется знать внешний IP-адрес и порт для подключения к вашему диспетчеру очередей.

2. Большое спасибо!. в моем случае он локальный, код C выполняется на хосте, а диспетчер очередей выполняется внутри контейнера. Я думаю, что следует использовать подход с разделяемой памятью, о котором вы упомянули, не уверен, возможно ли это с помощью Docker.

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

4. В итоге я установил переменную среды MQSERVER так, чтобы она указывала на tcp / 1414 на локальном хосте, где контейнер Docker прослушивает, и он работает. Ваш первый комментарий указал мне правильное направление. bash export MQSERVER=DEV.APP.SVRCONN/TCP/'localhost(1414)'

5. Обратите внимание, что использование этого параметра с MQCONN означает, что диспетчер очередей открыт для всех, кто может получить доступ к порту 1414 вашего контейнера docker. MQCONN не может передать аутентификацию по имени пользователя / паролю, а MQSERVER не допускает ничего другого, что обеспечивало бы какую-либо форму аутентификации. Если это только тестовая система, которая может быть в порядке, но тогда вам нужно когда-нибудь выяснить, как это сделать с аутентификацией в системе prod.

Ответ №1:

Если ваша программа будет выполняться на том же сервере, что и диспетчер очередей, то лучше связать ее с помощью ‘mqm.lib’ (режим привязки), а не ‘mqic.lib’ (режим клиента).

В Центре знаний MQ приведены примеры компиляции и компоновки вашей программы на языке Си. Примеры перечислены как «Клиентское приложение C» (клиентский режим) и «Серверное приложение C» (режим привязки).

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

Чтобы настроить вашу программу на языке Си для обеспечения надлежащей безопасности MQ, измените вызов API MQCONN на вызов API MQCONNX.

т.е.

 MQCNO   cno   = {MQCNO_DEFAULT};
MQCD    cd    = {MQCD_CLIENT_CONN_DEFAULT};
MQCSP   csp = {MQCSP_DEFAULT};

strncpy(cd.ConnectionName, hostname, MQ_CONN_NAME_LENGTH);
strncpy(cd.ChannelName, channelName, MQ_CHANNEL_NAME_LENGTH);

csp.AuthenticationType = MQCSP_AUTH_USER_ID_AND_PWD;

csp.CSPUserIdPtr = amp;myUserId;
csp.CSPUserIdOffset = 0;
csp.CSPUserIdLength = strlen(myUserId);

csp.CSPPasswordPtr = amp;myPassword;
csp.CSPPasswordOffset = 0;
csp.CSPPasswordLength = strlen(myPassword);

cno.cdPtr = amp;cd;
cno.Version = MQCNO_CURRENT_VERSION;
cno.SecurityParmsPtr = amp;csp;
cno.SecurityParmsOffset = 0;

MQCONNX(QMgrName, amp;cno, amp;Hcon, amp;CompCode, amp;Reason);
  

Несколько лет назад я написал сообщение в блоге под названием: Глаголы MQ API, которые IBM забыла!!. Я создал обертки для MQCONN и MQCONNX, которые позволят программе передавать идентификатор пользователя и пароль для вызовов API MQCONN и MQCONNX. Возможно, вам будет проще просто использовать оболочки.

Комментарии:

1. С 7.1 и более поздними версиями, если вы придерживаетесь библиотеки mqm, приложение может подключать привязку или клиент без каких-либо изменений кода, если вы используете mqic, оно может подключать только клиент.

2. @JoshMc верно, но я нахожу, что новички находят концепцию запутанной.