Practical mastering IBM MQ basics
Connection mode (3) client connection (2)
The Client Channel Definition Table (CCDT) allows you to define queue manager groups. It is possible to make a connection attempt to a queue manager belonging to that queue manager group.
*This series may be revised based on the latest mqpgf/mqpcf. Please always download and use the latest version.
Queue manager group
A queue manager group has the same QMNAME set in the client connection channel definition in CCDT. At this time, the queue manager group name specified in QMNAME does not have to match the actual queue manager name. As a special case, one with QMNAME set to ' ' (blank / space) is called the default queue manager group. To try to connect with a queue manager group, specify the queue manager group instead of specifying the queue manager name in the first argument of MQCONN() and MQCONNX() during a normal client connection. There are three ways to specify a character string to use a queue manager group:
1. Specify the queue manager group name as it is
In this case, connections are enforced only for queue managers with the same name as the queue manager group name. It does not connect to a queue manager whose actual queue manager name is different from the queue manager group name. If there are multiple queue managers with the same name, connections will be tried in order until the connection is successful.
2. The queue manager name is prefixed by an asterisk
If "*" is specified at the beginning, the connected queue manager name will not be checked. This is not the same as wildcards used in shells, command prompts, etc. A connection is tried in sequence using the connection definitions in the queue manager group until the connection is successful.
3. Only one astarisk or " "(blank/space) is set for the queue manager name
Connections are attempted in order using connection definitions within the default queue manager group with QMNAME set to '' (blank / space) in the client connection channel definition.
*In all the above cases, if multiple connections are targeted, the connection order will be in alphabetical order of the channel name in the default parameter settings (AFFINITY(PREFERRED), CLNTWGHT(0)).
This behavior can be changed in MQ 7.0 and later. (Described later)
Create a queue manager group verification environment
As an example, create the following test environment to check the basic behavior of CCDT.
Create a client connection channel(CHLTYPE: CLNTCONN) on the client side and a server connection channel(CHLTYPE: SVRCONN) on each queue manager on the server side. The client side and server side must be defined with the same channel name. This time, create each channel definition with a RUNMQSC script. The contents of the script read by each machine and queue manager are as follows: *In the runmqsc script, lines beginning with "*" are considered as comments. The "replace" at the end of the def(define's short form) command is an instruction to replace the definition with the specified content without an error if there is already a channel with the same name.
Script for client-side channel definition
>type clientChlDef.mqsc
* mqsc script for MQ Client machine channel definition.
* queue manager group: SampleQM
def chl('AG.SampleQM1.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1414)') QMNAME('SampleQM') replace
def chl('AG.SampleQM2.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1414)') QMNAME('SampleQM') replace
def chl('AG.SampleQM3.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1415)') QMNAME('SampleQM') replace
* queue manager group: PULSARGRP
def chl('BG.PULSARGRP1.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1415)') QMNAME('PULSARGRP') replace
def chl('BG.PULSARGRP2.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1416)') QMNAME('PULSARGRP') replace
* default queue manager group
def chl('CG.DEF1.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1414)') replace
def chl('CG.DEF2.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1415)') replace
def chl('CG.DEF3.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1414)') replace
def chl('CG.DEF4.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1415)') replace
def chl('CG.DEF5.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1416)') replace
>
Script for Server1 channel definition
*For Sample QM of Server1:
$ cat SampleQM.mqsc
* mqsc script for Server1 SampleQM channel definition.
* queue manager group: SampleQM
def chl('AG.SampleQM1.MQI') CHLTYPE(SVRCONN) replace
* default queue manager group
def chl('CG.DEF1.MQI') CHLTYPE(SVRCONN) replace
*For Remote QM of Server1:
$ cat RemoteQM.mqsc
* mqsc script for Server1 RemoteQM channel definition.
* queue manager group: SampleQM
def chl('AG.SampleQM3.MQI') CHLTYPE(SVRCONN) replace
* default queue manager group
def chl('CG.DEF2.MQI') CHLTYPE(SVRCONN) replace
Script for Server2 channel definition
*For SampleQM of Server2:
$ cat SampleQM.mqsc
* mqsc script for Server2 SampleQM channel definition.
* queue manager group: SampleQM
def chl('AG.SampleQM2.MQI') CHLTYPE(SVRCONN) replace
* default queue manager group
def chl('CG.DEF3.MQI') CHLTYPE(SVRCONN) replace
*For Remote QM of Server 2:
$ cat RemoteQM.mqsc
* mqsc script for Server2 RemoteQM channel definition.
* queue manager group: PULSARGRP
def chl('BG.PULSARGRP1.MQI') CHLTYPE(SVRCONN) replace
* default queue manager group
def chl('CG.DEF4.MQI') CHLTYPE(SVRCONN) replace
*For PartialQM of Server2:
$ cat PartialQM.mqsc
* mqsc script for Server2 PartialQM channel definition.
* queue manager group: PULSARGRP
def chl('BG.PULSARGRP2.MQI') CHLTYPE(SVRCONN) replace
* default queue manager group
def chl('CG.DEF5.MQI') CHLTYPE(SVRCONN) replace
Run the script to define a channel.
The mqsc script can be loaded into runmqsc with an input redirect("<").
On the server side, it can also be read by the mqpcf command.
Run the script for client-side channel definition
>runmqsc -n < clientChlDef.mqsc 5724-H72 (C) Copyright IBM Corp. 1994, 2018. 'AMQCLCHL.TAB' : * mqsc script for MQ Client machine channel definition. : : * queue manager group: SampleQM 1 : def chl('AG.SampleQM1.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1414)') QMNAME('SampleQM') replace AMQ8014I: 2 : def chl('AG.SampleQM2.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1414)') QMNAME('SampleQM') replace AMQ8014I: 3 : def chl('AG.SampleQM3.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1415)') QMNAME('SampleQM') replace AMQ8014I: : : * queue manager group: PULSARGRP 4 : def chl('BG.PULSARGRP1.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1415)') QMNAME('PULSARGRP') replace AMQ8014I: 5 : def chl('BG.PULSARGRP2.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1416)') QMNAME('PULSARGRP') replace AMQ8014I: : : * default queue manager group 6 : def chl('CG.DEF1.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1414)') replace AMQ8014I: 7 : def chl('CG.DEF2.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.3(1415)') replace AMQ8014I: 8 : def chl('CG.DEF3.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1414)') replace AMQ8014I: 9 : def chl('CG.DEF4.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1415)') replace AMQ8014I: 10 : def chl('CG.DEF5.MQI') CHLTYPE(CLNTCONN) CONNAME('10.41.207.4(1416)') replace AMQ8014I: *When runmqsc was run on the MQ9.1.0.0 client for Windows, garbled characters were displayed. Therefore that message part was omitted.
Execute channel creation script on Server1
[ SampleQM ] $ mqpcf mqsc -qm SampleQM -f SampleQM.mqsc MQSC Command [1] : def chl('AG.SampleQM1.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. MQSC Command [2] : def chl('CG.DEF1.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. [ RemoteQM ] $ mqpcf mqsc -qm RemoteQM -f RemoteQM.mqsc MQSC Command [1] : def chl('AG.SampleQM3.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. MQSC Command [2] : def chl('CG.DEF2.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. $
Execute channel creation script on Server 2
[ SampleQM ] $ mqpcf mqsc -qm SampleQM -f SampleQM.mqsc MQSC Command [1] : def chl('AG.SampleQM2.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. MQSC Command [2] : def chl('CG.DEF3.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. [ RemoteQM ] $ mqpcf mqsc -qm RemoteQM -f RemoteQM.mqsc MQSC Command [1] : def chl('BG.PULSARGRP1.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. MQSC Command [2] : def chl('CG.DEF4.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. [ PartialQM ] $ mqpcf mqsc -qm PartialQM -f PartialQM.mqsc MQSC Command [1] : def chl('BG.PULSARGRP2.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. MQSC Command [2] : def chl('CG.DEF5.MQI') CHLTYPE(SVRCONN) replace 1: AMQ8014: IBM MQ channel created. $
Just in case, recheck the channel definition table before testing.
>runmqsc -n 5724-H72 (C) Copyright IBM Corp. 1994, 2018. 'AMQCLCHL.TAB' dis chl(*) conname qmname 5 : dis chl(*) conname qmname AMQ8414I: CHANNEL(AG.SampleQM1.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.3(1414)) QMNAME(SampleQM) AMQ8414I: CHANNEL(AG.SampleQM2.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.4(1414)) QMNAME(SampleQM) AMQ8414I: CHANNEL(AG.SampleQM3.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.3(1415)) QMNAME(SampleQM) AMQ8414I: CHANNEL(BG.PULSARGRP1.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.4(1415)) QMNAME(PULSARGRP) AMQ8414I: CHANNEL(BG.PULSARGRP2.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.4(1416)) QMNAME(PULSARGRP) AMQ8414I: CHANNEL(CG.DEF1.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.3(1414)) QMNAME( ) AMQ8414I: CHANNEL(CG.DEF2.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.3(1415)) QMNAME( ) AMQ8414I: CHANNEL(CG.DEF3.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.4(1414)) QMNAME( ) AMQ8414I: CHANNEL(CG.DEF4.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.4(1415)) QMNAME( ) AMQ8414I: CHANNEL(CG.DEF5.MQI) CHLTYPE(CLNTCONN) CONNAME(10.41.207.4(1416)) QMNAME( )
Now test with some patterns.
Ex. 8.1 Specify the queue manager group name as it is (1)
Specify "SampleQM" as the queue manager name. The connection should be attempted to SampleQM on Server1 first, but keep this queue manager stopped.
Server1: dspmq QMNAME(SampleQM) STATUS(Ended normally) QMNAME(RemoteQM) STATUS(Running) Server2: dspmq QMNAME(SampleQM) STATUS(Running) QMNAME(RemoteQM) STATUS(Running) QMNAME(PartialQM) STATUS(Running)
Stop before MQDISC to check the connection status.
>mqpgfc -qm SampleQM -q LQ1 -m test -tr -s MQDISC
[2018/10/10 17:25:49.893] MQCONN start qmgr:SampleQM
[2018/10/10 17:25:55.862] MQCONN stop hcon:33554438 qmgr:SampleQM CompCd=00 ReasonCd=00
[2018/10/10 17:25:55.862] MQOPEN start hcon:33554438 ObjectName:LQ1 Options:0x00000010
[2018/10/10 17:25:55.893] MQOPEN stop hcon:33554438 ObjectName:LQ1 CompCd=00 ReasonCd=00
[2018/10/10 17:25:55.893] 1: message length: 4 put message: test
[2018/10/10 17:25:55.893] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/10 17:25:55.924] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/10 17:25:55.924] MQCLOSE start hcon:33554438 Options:0x00000000
[2018/10/10 17:25:55.955] MQCLOSE stop hcon:33554438 CompCd=00 ReasonCd=00
stop before calling MQDISC().
Hit Any Key!!!
From simple trace information, you can confirm that the connection to "Sample QM" is successful at one time for the MQCONN() call itself.
Check the client-side error log.
The default for Windows is "C:\ProgramData\IBM\MQ\errors\AMQERR01.LOG".
2018/10/16 09:43:05 - Process(13524.1) User(pulsar) Program(mqpgfc.exe) Host(CLIENT1) Installation(Installation2) VRMF(9.1.0.0) Time(2018-10-16T00:43:05.547Z) ArithInsert1(5) CommentInsert1(10.41.207.3) CommentInsert2(getnameinfo) AMQ9788W: .... '10.41.207.3'
You can see that the connection was attempted to Server1(10.41.207.3).
Check the connection to SampleQM on Server2.
$ mqpcf con -qm SampleQM APPLTAG | grep mqpgfc
15: CONN(414D514353616D706C65514D202020205BC533DB20002501) TYPE(ALL) APPLTAG(...mqpgfc.exe)
The connection for mqpgf has been created. From this, we can see that the first attempt to connect to the SampleQM on Server1 failed, and then the attempt to connect to the SampleQM on Server2 was successful.
Ex. 8.2 Specify the queue manager group name as it is (2)
Next, try stopping SampleQM of Server2.
Server1: dspmq QMNAME(SampleQM) STATUS(Ended normally) QMNAME(RemoteQM) STATUS(Running) Server2: dspmq QMNAME(SampleQM) STATUS(Ended normally) QMNAME(RemoteQM) STATUS(Running) QMNAME(PartialQM) STATUS(Running)
Try to connect in the same way as before. Now collect MQ traces to make sure the connection attempts are being made as expected. The MQ trace will be explained again, so for the time being, try collecting the MQ trace by executing the strmqtrc(start MQ trace) and endmqtrc(end MQ trace) commands as shown below.
>strmqtrc -e -t detail -t all
IBM MQ tracing has been started on installation 'Installation1'.
>mqpgfc -qm SampleQM -q LQ1 -m test -tr
[2018/10/16 09:49:21.216] MQCONN start qmgr:SampleQM
[2018/10/16 09:49:28.814] MQCONN stop hcon:-1 qmgr:SampleQM CompCd=02 ReasonCd=2058
MQCONN fail : SampleQM CompCd=02 ReasonCd=2058
!!! Queue Manager Connect Fail SampleQM !!!
>endmqtrc -e
IBM MQ tracing has stopped at installation 'Installation1'.
An attempt was made to connect to RemoteQM on Server1 using AG.SampleQM3.MQI, but the connection failed with reason code 2058 MQRC_Q_MGR_NAME_ERROR because the queue manager name was "RemoteQM" instead of "SampleQM".
Also check the error log.
2018/10/16 10:09:30 - Process(11052.1) User(pulsar) Program(mqpgfc.exe) Host(CLIENT1) Installation(Installation2) VRMF(9.1.0.0) Time(2018-10-16T01:09:30.725Z) ArithInsert1(4) CommentInsert1(10.41.207.3) CommentInsert2(getnameinfo) AMQ9788W: .... '10.41.207.3'
As far as I tested with the MQ9.1.0.0 client, only one message that failed to connect to Server1 was logged.
This does not tell if the connection was attempted as expected.
Check the collected MQ trace.
An MQ trace is created for each process with the extension TRC under a directory called trace under the MQ data directory.
The default is:
Windows | C:\ProgramData\IBM\MQ\trace |
Unix/Linux | /var/mqm/trace |
*Since there is no readability other than Windows, execute the following command to create a readable *.FMT file.
$ cd /var/mqm/trace
$ dspmqtrc *.TRC (convert all trace files)
*MQ trace output format is private, and the output contents differ depending on the version and platform. The following is just for the MQ9.1.0.0 Windows client.
The first line of each MQ trace contains the name of the program to be traced.
Process : C:\Users\pulsar\mqpgfc.exe (32-bit)
Below is an excerpt of the mqpgfc.exe MQ trace file.
000020A3 10:09:25.146304 11052.1 RSESS:000001 SELECT CHANNEL
0000245C 10:09:30.742504 11052.1 RSESS:000001 RetCode = 20009202, rc1 = 10061, rc2 = 10061, Comment1 = '10.41.207.3 (1414)',....
0000245D 10:09:30.742556 11052.1 RSESS:000001 ------------}! rrxError (rc=rrcE_HOST_NOT_AVAILABLE)
000024C0 10:09:30.746526 11052.1 RSESS:000001 SELECT CHANNEL
0000257F 10:09:31.779507 11052.1 RSESS:000001 RetCode = 20009202, rc1 = 10061, rc2 = 10061, Comment1 = '10.41.207.4 (14141)',....
00002580 10:09:31.779589 11052.1 RSESS:000001 ------------}! rrxError (rc=rrcE_HOST_NOT_AVAILABLE)
000025ED 10:09:31.784075 11052.1 RSESS:000001 SELECT CHANNEL
00002B3F 10:09:31.926874 11052.1 : !! - MQI:MQCONN HConn=FFFFFFFF rc=0000080A
Connection attempts were made in the order AG.SampleQM1.MQI, AG.SampleQM2.MQI, AG.SampleQM3.MQI, the first two failed with HOST_NOT_AVAILABLE, and the last attempted connection recorded rc = 000080A as the reason code. This is the hexadecimal code that indicates MQRC_Q_MGR_NAME_ERROR as shown below.
>mqrc 2058
2058 0x0000080a MQRC_Q_MGR_NAME_ERROR
Ex. 8.3 Specifying the Queue Manager Group Name as It is (3)
Next, try to specify PULSARGRP as it is.
>mqpgfc -qm PULSARGRP -q LQ1 -m test -tr [2018/10/11 10:16:40.437] MQCONN start qmgr:PULSARGRP [2018/10/11 10:16:41.171] MQCONN stop hcon:-1 qmgr:PULSARGRP CompCd=02 ReasonCd=2058 MQCONN fail : PULSARGRP CompCd=02 ReasonCd=2058 !!! Queue Manager Connect Fail PULSARGRP !!!
The connection is attempted to RemoteQM on Server2 using BG.PULSARGRP1.MQI and to PartialQM on Server2 using BG.PULSARGRP2.MQI, but both fail with reason code 2058 MQRC_Q_MGR_NAME_ERROR because they have different queue manager names. At this time, nothing is output to the error log.
Ex. 8.4 A queue manager group name is prefixed by an asterisk
This time, try executing the command with "*" at the beginning("*PULSARGRP").
>mqpgfc -qm "*PULSARGRP" -q LQ1 -m test -tr -s MQDISC [2018/10/11 10:24:43.187] MQCONN start qmgr:*PULSARGRP [2018/10/11 10:24:43.328] MQCONN stop hcon:33554438 qmgr:*PULSARGRP CompCd=00 ReasonCd=00 [2018/10/11 10:24:43.328] MQOPEN start hcon:33554438 ObjectName:LQ1 Options:0x00000010 [2018/10/11 10:24:43.344] MQOPEN stop hcon:33554438 ObjectName:LQ1 CompCd=00 ReasonCd=00 [2018/10/11 10:24:43.344] 1: message length: 4 put message: test [2018/10/11 10:24:43.359] MQPUT start hcon:33554438 Options:0x00000000 [2018/10/11 10:24:43.375] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00 [2018/10/11 10:24:43.390] MQCLOSE start hcon:33554438 Options:0x00000000 [2018/10/11 10:24:43.406] MQCLOSE stop hcon:33554438 CompCd=00 ReasonCd=00 stop before calling MQDISC(). Hit Any Key!!!
The connection is successful. Check which queue manager it is connected to.
Server2: mqpcf con -qm RemoteQM APPLTAG | grep mqpgf
17: CONN(414D514352656D6F7465514D202020205BBE9C2720002403) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
You can confirm that it is connected to Remote QM of Server2.
Ex. 8.5 One astarisk is set for the queue manager name
Finally, test by specifying "*" one character. You may specify only blanks (" ").
>mqpgfc -qm "*" -q LQ1 -m test -tr -s MQDISC
[2018/10/11 10:30:48.927] MQCONN start qmgr:*
[2018/10/11 10:30:54.838] MQCONN stop hcon:33554438 qmgr:* CompCd=00 ReasonCd=00
[2018/10/11 10:30:54.838] MQOPEN start hcon:33554438 ObjectName:LQ1 Options:0x00000010
[2018/10/11 10:30:54.885] MQOPEN stop hcon:33554438 ObjectName:LQ1 CompCd=00 ReasonCd=00
[2018/10/11 10:30:54.885] 1: message length: 4 put message: test
[2018/10/11 10:30:54.885] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/11 10:30:54.916] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/11 10:30:54.916] MQCLOSE start hcon:33554438 Options:0x00000000
[2018/10/11 10:30:54.931] MQCLOSE stop hcon:33554438 CompCd=00 ReasonCd=00
stop before calling MQDISC().
Hit Any Key!!!
The connection seems to be successful, so check which queue manager it is connected to.
Server1: mqpcf con -qm RemoteQM APPLTAG | grep mqpgf
30: CONN(414D514352656D6F7465514D202020205BBE9C3220002401) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Server1's RemoteQM is the default queue manager group(QMNAME is blank) and is the first and running queue manager in alphabetical order for channels.
Automatic client reconnection
The function of automatic reconnection of MQ client is available from MQ7.0.1. This is a very useful feature that automatically tries to reconnect if the MQ connection is lost without changing the existing source code. For example, if MQRC_CONNECTION_BROKEN is received as a return value, the application does not need to invoke MQCONN() again. Any point in the client application program is automatically reconnected. In order to use this feature, the application needs to be linked with the MQ thread library.
Enabling automatic client reconnection
There are three ways to enable automatic client reconnection:
- 1. Set the DefRecon attribute of the channel stanza in the mqclient.ini configuration file to YES or QMGR
- 2. Set YES or QMGR to DEFRECON of client connection channel (CLNTCONN) in CCDT
- 3. Use MQCONNX() and set MQCNO_RECONNECT or MQCNO_RECONNECT_Q_MGR of MQCNO option
"YES" to be set to the DEFRecon parameter of RefRecon or CLNTCONN of qmclient.ini corresponds to MQCNO_RECONNECT, and "QMGR" corresponds to MQCNO_RECONNECT_Q_MGR. When combined with the functions of the CCDT queue manager group, it is possible to reconnect to another QMGR and continue processing in the event of a connection failure.
Registering event handler
The client's automatic reconnection is done automatically, so the client application may not notice that the reconnection has been made. You can register an event handler to know if the application has been reconnected and its status. Registering an event handler allows you to receive notifications when the following events occur: (Registration of an event handler is not mandatory.)
MQRC_RECONNECTING | Attempting to reconnect. (Occurs whenever a reconnection attempt is made) |
MQRC_RECONNECTED | Reconnect completed successfully. |
MQRC_RECONNECT_FAILED | Reconnection failure. |
In addition, events with reason codes such as MQRC_RECONNECT_QMID_MISMATCH, MQRC_RECONNECT_Q_MGR_REQD, MQRC_RECONNECT_INCOMPATIBLE, and MQRC_CALL_INTERRUPTED are also notified. Please refer to the product manual for an explanation of these.
The function registered as an event handler is a callback function registered using MQCB()(Manage callback), the content is created by the user, but the form of the call is determined as follows.
MQCB_FUNCTION (Hconn, MsgDesc, GetMsgOpts, Buffer, Context)
The reason code for which the callback function was called is returned to Reason in Context.
The function name is freely.
The calling format of MQCB() is as follows.
MQCB (Hconn, Operation, CallbackDesc, Hobj, MsgDesc, GetMsgOpts, CompCode, Reason)
For event handlers, specify MQOP_REGISTER for Operation and MQCBT_EVENT_HANDLER for CallbackDesc.CallbackType.
Then, set CallbackDesc.CallbackFunction to the function pointer of the created event handler.
Since Hobj, MsgDesc, and GetMsgOpts are not used, set MQHO_NONE for Hobj and NULL for MsgDesc and GetMsgOpts.
mqpgf/mqpgfc has a predefined event handler.
It simply shows what was set in Context.Reason when the event handler was called back and the value of Context.ReconnectDelay.
And it's almost the same as the source code provided as a sample for MQ.
The value of ReconnectDelay when referenced in the event handler represents the amount of time (ms) to wait until the next attempt to reconnect.
The following is a sample program for high availability related to client automatic reconnection. Please refer to it as needed.
amqsphac.c | MQPUT application |
amqsghac.c | MQGET application |
amqsmhac.c | Application that transfers messages from queue to queue. |
amqsfhac.c | Perform put/get under the synchronization point and check that the data integrity is maintained after a failure. |
Ex. 8.6 Automatic Reconnection of Queue Manager Group and Client
Use the same configuration as when testing the queue manager group to see how it reconnects.
Use the "SampleQM" queue manager group and add "*" at the beginning to enable connection to all three queue managers including RemoteQM.
The command line to execute from the client is as follows.
Specify MQCNO_RECONNECT to connect to other queue managers in the same queue manager group if a connection error is detected.
It also tells the command to call a specific event handler.
With this command, MQCONN() is called only once at the beginning and MQPUT() is repeated 100 times at 1 second intervals.
mqpgfc -qm "*SampleQM" -q LQ1 -m test -tr -n 100 -i 1000 -cf EventHandler -op MQOP_REGISTER MQCBT_EVENT_HANDLER MQCNO_RECONNECT
*Option descriptions
-cf EventHandler: Specify the mqpgf/mqpgfc specific event handler as the callback function
-op MQOP_REGISTER: Set MQCB.Operation to MQOP_REGISTER
MQCBT_EVENT_HANDLER: Set MQCBD.CallbackType to MQCBT_EVENT_HANDLER
MQCNO_RECONNECT: Set MQCNO_RECONNECT of MQCNO.Options
Now, start the command execution with all the SampleQM of Server1, SampleQM of Server2, and RemoteQM of Server1 activated. In orderly, stop SampleQM of Server1, SampleQM of Server2, RemoteQM of Server1, and check which queue manager it is reconnected to using the "con" command of mqpcf on the server side. Finally, start SampleQM of Server2 and check that it is connected properly. The method of removing the connection is freely, such as unplugging the LAN cable, but note that running endmqm without an argument does not enable client automatic reconnection. When ending the queue manager with endmqm, if the "-r" option is specified, an attempt is made to reconnect the client. This time, use this method.
>mqpgfc -qm "*SampleQM" -q LQ1 -m test -tr -n 100 -i 1000 -cf EventHandler -op MQOP_REGISTER MQCBT_EVENT_HANDLER MQCNO_RECONNECT
[2018/10/16 13:30:56.053] MQCONNX start qmgr:*SampleQM Options:0x01000000
[2018/10/16 13:30:56.521] MQCONNX stop hcon:33554438 qmgr:*SampleQM CompCd=00 ReasonCd=00
[2018/10/16 13:30:56.521] MQCB start hcon:33554438
[2018/10/16 13:30:56.521] MQCB stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:30:56.521] MQOPEN start hcon:33554438 ObjectName:LQ1 Options:0x00000010
[2018/10/16 13:30:56.568] MQOPEN stop hcon:33554438 ObjectName:LQ1 CompCd=00 ReasonCd=00
[2018/10/16 13:30:56.568] 1: message length: 4 put message: test
[2018/10/16 13:30:56.568] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:30:56.584] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:30:57.600] 2: message length: 4 put message: test
[2018/10/16 13:30:57.600] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:30:57.600] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
....
After confirming that it is connected to the SampleQM on Server1, stop the SampleQM on Server1 with the "-r" option.
Server1: mqpcf con -qm SampleQM APPLTAG |grep mqpgfc
37: CONN(414D514353616D706C65514D202020205BC5697920002302) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Server1: endmqm -r SampleQM
Quiesce request accepted. The queue manager will stop when all outstanding work is complete.
....
[2018/10/16 13:31:12.834] 17: message length: 4 put message: test
[2018/10/16 13:31:12.834] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:12.834] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:31:13.443] EVENT : Reconnecting (Delay: 95ms)
[2018/10/16 13:31:13.865] 18: message length: 4 put message: test
[2018/10/16 13:31:13.865] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:19.209] EVENT : Reconnected
[2018/10/16 13:31:19.975] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:31:20.990] 19: message length: 4 put message: test
[2018/10/16 13:31:20.990] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:21.006] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
....
After confirming that it is connected to SampleQM on Server2, stop SampleQM on Server2 with the "-r" option.
Server2: mqpcf con -qm SampleQM APPLTAG |grep mqpgfc
29: CONN(414D514353616D706C65514D202020205BC569842000230B) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Server2: endmqm -r SampleQM
Quiesce request accepted. The queue manager will stop when all outstanding work is complete.
....
[2018/10/16 13:31:38.509] 36: message length: 4 put message: test
[2018/10/16 13:31:38.509] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:38.509] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:31:38.900] EVENT : Reconnecting (Delay: 167ms)
[2018/10/16 13:31:39.541] 37: message length: 4 put message: test
[2018/10/16 13:31:39.541] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:46.134] EVENT : Reconnected
[2018/10/16 13:31:46.681] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:31:47.697] 38: message length: 4 put message: test
[2018/10/16 13:31:47.697] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:47.713] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
....
After confirming that it is connected to RemoteQM on Server1, stop RemoteQM on Server1 with the "-r" option.
Server1: mqpcf con -qm RemoteQM APPLTAG |grep mqpgfc
25: CONN(414D514352656D6F7465514D202020205BC5695220002302) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Server1: endmqm -r RemoteQM
....
[2018/10/16 13:31:58.936] 49: message length: 4 put message: test
[2018/10/16 13:31:58.936] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:58.936] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:31:59.956] 50: message length: 4 put message: test
[2018/10/16 13:31:59.956] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:31:59.956] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:32:00.815] EVENT : Reconnecting (Delay: 213ms)
[2018/10/16 13:32:00.971] 51: message length: 4 put message: test
[2018/10/16 13:32:00.971] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:32:13.159] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 13:32:25.268] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 13:32:37.410] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 13:32:49.551] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 13:33:01.754] EVENT : Reconnecting (Delay: 7440ms)
[2018/10/16 13:33:21.336] EVENT : Reconnecting (Delay: 18892ms)
....
The client retries repeatedly because all members of the "SampleQM" queue manager group have stopped.
This retry interval will gradually increase.
*In this test, when the queue manager is stopped with endmqm -r, the retry interval is returned as 0 ms from the second time several times.
Finally, start SampleQM of Server2.
Server2: strmqm SampleQM
IBM MQ queue manager 'SampleQM' starting.
IBM MQ queue manager 'SampleQM' started using V8.0.3.0.
....
[2018/10/16 13:33:46.009] EVENT : Reconnected
[2018/10/16 13:33:46.524] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:33:47.540] 52: message length: 4 put message: test
[2018/10/16 13:33:47.540] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:33:47.556] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 13:33:48.571] 53: message length: 4 put message: test
[2018/10/16 13:33:48.571] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 13:33:48.587] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
....
Confirm that it is connected to SampleQM on Server2.
Server2: mqpcf con -qm SampleQM -t APPLTAG |grep mqpgfc
[18/10/16 13:34:47.583089] 48: CONN(414D514353616D706C65514D202020205BC56A5320001A05) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Change connection timeout
You can set the connection timeout time in the MQReconnectTimeout parameter of the CHANNELS stanza in mqclient.ini. The default value is 1800 seconds (30 minutes). Set as below.
CHANNELS:
MQReconnectTimeout=120
Ex. 8.7 Behavior when client auto-reconnect times out
Set the automatic reconnection timeout to 120(2 minutes) and check the behavior just in case. All queue managers in the SampleQM group are in a stopped state.
>mqpgfc -qm "*SampleQM" -q LQ1 -m test -tr -n 100 -i 1000 -cf EventHandler -op MQOP_REGISTER MQCBT_EVENT_HANDLER MQCNO_RECONNECT_Q_MGR[2018/10/16 15:38:31.670] MQCONNX start qmgr:*SampleQM Options:0x04000000
[2018/10/16 15:38:32.029] MQCONNX stop hcon:33554438 qmgr:*SampleQM CompCd=00 ReasonCd=00
[2018/10/16 15:38:32.029] MQCB start hcon:33554438
[2018/10/16 15:38:32.029] MQCB stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 15:38:32.029] MQOPEN start hcon:33554438 ObjectName:LQ1 Options:0x00000010
[2018/10/16 15:38:32.092] MQOPEN stop hcon:33554438 ObjectName:LQ1 CompCd=00 ReasonCd=00
[2018/10/16 15:38:32.092] 1: message length: 4 put message: test
[2018/10/16 15:38:32.092] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 15:38:32.107] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 15:38:33.123] 2: message length: 4 put message: test
[2018/10/16 15:38:33.123] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 15:38:33.123] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
....
*Stop all queue managers here with "endmqm -r"
....
[2018/10/16 15:38:38.232] 7: message length: 4 put message: test
[2018/10/16 15:38:38.232] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 15:38:38.232] MQPUT stop hcon:33554438 CompCd=00 ReasonCd=00
[2018/10/16 15:38:38.670] EVENT : Reconnecting (Delay: 90ms)
[2018/10/16 15:38:39.248] 8: message length: 4 put message: test
[2018/10/16 15:38:39.248] MQPUT start hcon:33554438 Options:0x00000000
[2018/10/16 15:38:50.893] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:39:03.002] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:39:15.143] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:39:27.268] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:39:39.393] EVENT : Reconnecting (Delay: 3880ms)
[2018/10/16 15:39:55.455] EVENT : Reconnecting (Delay: 21673ms)
[2018/10/16 15:40:29.268] EVENT : Reconnecting (Delay: 17862ms)
[2018/10/16 15:40:29.268] EVENT : Reconnection failed
[2018/10/16 15:40:29.268] EVENT : Connection Broken
[2018/10/16 15:40:29.862] MQPUT stop hcon:33554438 CompCd=02 ReasonCd=2548
MQPUT fail : LQ1 CompCd=02 ReasonCd=2548
*Reconnection fails about 2 minutes after reconnection starts, following MQRC_RECONNECT_FAILED(Reconnection failed), MQRC_CONNECTION_BROKEN(Connection Broken) event has occurred. The MQPUT() call then returns reason code 2548 MQRC_RECONNECT_FAILED. mqpgf always ends with calling MQCLOSE() and MQDISC() regardless of the reason code. Therefore, client automatic reconnection occurs again while calling MQDISC(). Actual business applications need to consider this behavior.
[2018/10/16 15:40:29.862] MQCLOSE start hcon:33554438 Options:0x00000000
[2018/10/16 15:40:29.877] MQCLOSE stop hcon:33554438 CompCd=02 ReasonCd=2548
MQCLOSE fail : CompCd=02 ReasonCd=2548
[2018/10/16 15:40:29.877] MQDISC start hcon:33554438
[2018/10/16 15:40:59.252] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:41:11.377] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:41:23.518] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:41:35.643] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:43:15.973] EVENT : Reconnecting (Delay: 0ms)
[2018/10/16 15:43:15.973] EVENT : Reconnection failed
[2018/10/16 15:43:16.317] MQDISC stop hcon:-1 CompCd=02 ReasonCd=2548
MQDISC fail : CompCd=02 ReasonCd=2548
Finally, previous tests did not confirm, but MQRC_CALL_INTERRUPTED may be returned in the MQPUT() or MQCMIT() reason code when client auto-reconnect is enabled. If the application receives this, it indicates that the MQ client is in a situation where it can not know if the message was successfully sent. In this case, the application needs to consider, for example, retransmission of the message.