実践習得 IBM MQの基本
接続モード(3)クライアント接続(2)
クライアント・チャネル定義テーブル (CCDT) を使用すると、キューマネージャー・グループを定義できます。 そのキューマネージャー・グループに所属するキューマネージャーに対して接続を試行させることが可能です。
※本連載は最新のmqpgf/mqpcfに基づいて改定されることがあります。常に最新バージョンをダウンロードしてご使用ください。
キューマネージャー・グループ
CCDT内のクライアント接続チャネル定義内で同一QMNAMEが設定されているものがキューマネージャー・グループです。 この時、QMNAMEに指定されるキューマネージャー・グループ名は実際のキューマネージャー名と一致している必要はありません。 特殊なものとして、QMNAMEが' '(ブランク/スペース)に設定されているものを、デフォルトのキューマネージャー・グループと呼びます。 キューマネージャー・グループで接続を試行させるには、通常のクライアント接続時にMQCONN()、MQCONNX()の第一引数にキューマネージャー名を指定する代わりに、キューマネージャー・グループを指定します。 キューマネージャー・グループを使用する為の文字列の指定方法には下記の3つがあります。
1. キューマネージャー・グループ名をそのまま指定する。
この場合、キューマネージャー・グループ名と同じ名前のキューマネージャーに対してのみ接続が施行されます。 実際のキューマネージャー名がキューマネージャー・グループ名と異なるキューマネージャーには接続されません。 同一名称のキューマネージャーが複数ある場合は接続が成功するまで、順番に接続が試行されます。
2. 先頭に"*"を付加したキューマネージャー・グループを指定する。
先頭に"*'を指定した場合は、接続先のキューマネージャー名はチェックされません。 シェルやコマンド・プロンプト等で使用させるワイルドカードとは意味が違います。 接続が成功するまで、キューマネージャー・グループ内の接続定義を使用して順番に接続が試行されます。
3. "*"一文字のみ、または" "(ブランク/スペース)のみを指定する。
クライアント接続チャネル定義でQMNAMEが' '(ブランク/スペース)に設定されているデフォルトのキューマネージャー・グループの内の接続定義を使用して順番に接続が試行されます。
※上記の全てのケースで、複数の接続が対象になった場合、デフォルトのパラメータ設定(AFFINITY(PREFERRED)、CLNTWGHT(0))では接続順はチャネル名のアルファベット順になります。
MQ7.0以降はこの動作を変更することができます。(後述)
キューマネージャー・グループの検証環境の作成
例として、下記のテスト環境を作成してCCDTの基本的な挙動を確認してみます。
クライアント側にクライアント接続チャネル(CHLTYPE:CLNTCONN)とサーバー側の各キューマネージャーにサーバー接続チャネル(CHLTYPE:SVRCONN)を作成します。 クライアント側とサーバー側は同一のチャネル名で定義することが必要です。 今回は各チャネル定義をRUNMQSCで読み込ませるスクリプトで作成してみます。 各マシン、キューマネージャーで読み込ませるスクリプトの内容は下記です。 ※runmqscのスクリプトは、"*"で始まる行はコメントとみなされます。 def(defineの短縮形)コマンドの末尾の"replace"は、同じ名前のチャネル手以外が既に存在する場合にエラーにせずに定義を指定した内容に置き換える指示です。
クライアント側のチャネル作成スクリプト
>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
>
Server1のチャネル作成スクリプト
※Server1のSampleQM用:
$ 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
※Server1のRemoteQM用:
$ 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
Server2のチャネル作成スクリプト
※Server2のSampleQM用:
$ 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
※Server2のRemoteQM用:
$ 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
※Server2のPartialQM用:
$ 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
スクリプトを実行させてチャネルを作成します。
mqscのスクリプトは、runmqscへ入力リダイレクト("<")で読み込ませることができます。
サーバー側ではmqpcfコマンドから読み込ませることもできます。
クライアント側のチャネル作成スクリプトの実行
>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: ※Windows版のMQクライアントでrunmqscを実行したところ、MQ9.1.0.0の時点では文字化けが発生していました。 その為メッセージ部分は省略しています。
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. $
Server2でのチャネル作成スクリプトの実行
[ 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. $
テスト前に念の為、チャネル定義テーブルを再チェックしてみます。
>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( )
それではいくつかのパターンでテストしてみます。
Ex. 8.1 キューマネージャー・グループ名をそのまま指定(1)
キューマネージャー名に"SampleQM"を指定します。 最初にServer1のSampleQMに接続が試行されるはずですが、このキューマネージャーを停止しておきます。
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)
接続を確認する為にMQDISC前で停止させます。
>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!!!
簡易トレース情報からMQCONN()呼び出し自体は1回で"SampleQM"に接続が成功していることが確認できます。
クライアント側のエラーログを確認してみます。
Windowsの場合のデフォルトは、"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'
Server1(10.41.207.3)に接続に行こうとしたことが分かります。
Server2のSampleQMへの接続を確認してみます。
$ mqpcf con -qm SampleQM APPLTAG | grep mqpgfc
15: CONN(414D514353616D706C65514D202020205BC533DB20002501) TYPE(ALL) APPLTAG(...mqpgfc.exe)
mqpgfの接続が確認できます。 このことから、Server1のSampleQMに最初に接続を試行して失敗した後、Server2のSampleQMに接続を試行して、成功したことが分かります。
Ex. 8.2 キューマネージャー・グループ名をそのまま指定(2)
次にServer2のSampleQMも停止してみます。
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)
先ほど同じ様に接続をこころみます。 ここで、想定通りに接続の試行が行われていることを確認する為にMQトレースを取得してみます。 MQトレースについては機会を改めてご説明したいと思いますので、とりあえす、下記の通りにstrmqtrc(MQトレースの開始)とendmqtrc(MQトレースの終了)コマンドを実行してMQトレースを取得してみてください。
>strmqtrc -e -t detail -t all
インストール済み環境 'Installation1' における IBM MQ のトレースが開始されました。
>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
インストール済み環境 'Installation1' における IBM MQ のトレースが停止しました。
Server1のRemoteQMへAG.SampleQM3.MQIを使用して接続を試行したが、キューマネージャー名が"SampleQM"ではなく、"RemoteQM"であったために理由コード 2058 MQRC_Q_MGR_NAME_ERRORで接続が失敗しています。
エラー・ログも確認します。
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'
MQ9.1.0.0クライアントでテストした限りでは、Server1への接続で失敗したログのみが記録されていました。
これでは、想定通りに接続が試行されたのかが分かりません。
取得したMQトレースの確認してみます。
MQトレースはMQのデータディレクトリ直下のtraceというディレクトリ下に拡張子TRCでプロセス毎に作成されます。
デフォルトは下記です。
Windows | C:\ProgramData\IBM\MQ\trace |
Unix/Linux | /var/mqm/trace |
※Windows以外は可読性がないので、下記コマンドを実行して可読性のある*.FMTファイルを作成します。
$ cd /var/mqm/trace
$ dspmqtrc *.TRC(全てのトレースファイルを変換する)
※MQトレースの出力形式は非公開となっており、またバージョンやプラット・フォームによって出力される内容が異なります。 以下は、あくまでMQ9.1.0.0 Windowsクライアントの場合です。
各MQトレースの先頭行にトレース対象のプログラム名が記録されています。
Process : C:\Users\pulsar\mqpgfc.exe (32-bit)
下記はmqpgfc.exeのMQトレースファイルの抜粋です。
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
AG.SampleQM1.MQI、AG.SampleQM2.MQI、AG.SampleQM3.MQIの順で接続が試行され、最初の2つがHOST_NOT_AVAILABLEで失敗し、最後に試行した接続で、rc=0000080Aが理由コードとして記録されています。 これは、下記の通りMQRC_Q_MGR_NAME_ERRORを示す16進数のコードです。
>mqrc 2058
2058 0x0000080a MQRC_Q_MGR_NAME_ERROR
Ex. 8.3 キューマネージャー・グループ名をそのまま指定(3)
次にPULSARGRPをそのまま指定してみます。
>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 !!!
BG.PULSARGRP1.MQIで、Server2のRemoteQM、BG.PULSARGRP2.MQIで、Server2のPartialQMへ接続に行きますが、どちらもキューマネージャー名が異なるので理由コード 2058 MQRC_Q_MGR_NAME_ERRORで接続に失敗します。 この時エラーログにはなにも出力されません。
Ex. 8.4 先頭に"*"を付加したキューマネージャー・グループを指定
今度は先頭に"*"を付与して、"*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!!!
接続に成功しています。 どのキューマネージャーに接続されているか確認します。
Server2: mqpcf con -qm RemoteQM APPLTAG | grep mqpgf
17: CONN(414D514352656D6F7465514D202020205BBE9C2720002403) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Server2のRemoteQMに接続されていることが確認できます。
Ex. 8.5 "*"一文字のみを指定
最後に"*"一文字を指定してテストしてみます。 ブランクのみ(" ")を指定しても構いません。
>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!!!
接続に成功しているようなので、どのキューマネージャーに接続されているか確認します。
Server1: mqpcf con -qm RemoteQM APPLTAG | grep mqpgf
30: CONN(414D514352656D6F7465514D202020205BBE9C3220002401) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
Server1のRemoteQMは、デフォルトのキューマネージャー・グループ(QMNAMEがブランク)のアルファベット順のチャネルが指すキューマネージャーで、起動している最初のキューマネージャーです。
クライアントの自動再接続
MQ7.0.1よりMQクライアントの自動再接続の機能が使用可能になりました。 これは、既存のソース・コードを変更なしに、MQ接続が失われた場合に自動的に再接続が試行されるという大変便利な機能です。 例えば、MQRC_CONNECTION_BROKENを戻り値として受け取った場合に、MQCONN()の再呼び出しをアプリケーションが実行する必要はありません。 クライアント・アプリケーション・プログラムのどのポイントでも自動的に再接続されます。 この機能を使用する為には、アプリケーションがMQのスレッド・ライブラリにリンクされていることが必要です。
クライアントの自動再接続の有効化
クライアントの自動再接続を有効にするには、下記の3つの方法があります。
- 1.mqclient.ini構成ファイル内のチャネル・スタンザのDefRecon属性にYESまたはQMGRを設定
- 2.CCDTでクライアント接続チャネル(CLNTCONN)のDEFRECONにYESまたはQMGRを設定
- 3.MQCONNX()を使用し、MQCNOオプションにMQCNO_RECONNECTまたはMQCNO_RECONNECT_Q_MGRを設定
qmclient.iniのRefReconまたはCLNTCONNのDEFRECONパラメータに設定する"YES"はMQCNO_RECONNECT、"QMGR"はMQCNO_RECONNECT_Q_MGRに対応します。 CCDTのキューマネージャー・グループの機能と組み合わると、接続障害時に別のQMGRに再接続して処理を継続することも可能です。
イベント・ハンドラーの登録
クライアントの自動再接続は、自動的に行われる為、クライアントのアプリケーションが再接続が行われたことに気づかない場合があります。 アプリケーションが再接続が行われたかどうか、およびその状況を知るために、イベント・ハンドラを登録することができます。 イベント・ハンドラを登録すると下記のイベントが発生した時に、通知を受け取ることができます。 イベント・ハンドラの登録は必須ではありません。
MQRC_RECONNECTING | 再接続の試行中。(再接続が試行される度に発生) |
MQRC_RECONNECTED | 再接続が正常に完了。 |
MQRC_RECONNECT_FAILED | 再接続失敗。 |
それ以外に、MQRC_RECONNECT_QMID_MISMATCH、MQRC_RECONNECT_Q_MGR_REQD、MQRC_RECONNECT_INCOMPATIBLE、MQRC_CALL_INTERRUPTEDといった理由コードのイベントも通知されます。 これらについての説明は製品マニュアルをご参照ください。
イベント・ハンドラとして登録する関数は、MQCB()(コールバック管理)を使用して登録するコールバック関数で、内容はユーザーが作成しますが、呼び出しの形式は下記のように決まっています。
MQCB_FUNCTION (Hconn, MsgDesc, GetMsgOpts, Buffer, Context)
コールバック関数が呼び出された理由コードは、ContextのReasonに戻されます。
関数名は任意です。
MQCB()の呼び出し形式は下記です。
MQCB (Hconn, Operation, CallbackDesc, Hobj, MsgDesc, GetMsgOpts, CompCode, Reason)
イベント・ハンドラーの場合は、OperationにMQOP_REGISTERを、CallbackDesc.CallbackTypeにMQCBT_EVENT_HANDLER指定します。
そして、CallbackDesc.CallbackFunctionに作成したイベント・ハンドラーの関数ポインタを設定します。
Hobj、MsgDesc、GetMsgOptsは使用しませんので、HobjにはMQHO_NONE、MsgDesc、GetMsgOptsはNULLを設定しておきます。
mqpgf/mqpgfcは、規定のイベント・ハンドラーを持っています。
これは、単純にイベント・ハンドラーがコール・バックされた時に、Context.Reasonに何が設定されていたかと、Context.ReconnectDelayの値を表示するもので、MQにサンプルとして提供されているソース・コードに含まれているものとほとんど同じです。
イベント・ハンドラー内で参照した時のReconnectDelayの値は、次回再接続を試みるまで待つ時間(ms)を表します。
下記がクライアント自動再接続に関連した高可用性のサンプルプログラムです。 必要に応じて参考にしてみてください。
amqsphac.c | MQPUTアプリケーション |
amqsghac.c | MQGETアプリケーション |
amqsmhac.c | キューからキューへメッセージを転送するアプリケーション |
amqsfhac.c | 同期点下でput/getを行い、障害後もデータ保全性を維持していることを検査 |
Ex. 8.6 キューマネージャー・グループとクライアントの自動再接続
キューマネージャー・グループのテストの時と同じ構成を使用して、再接続の様子を確認してみます。
"SampleQM"キューマネージャー・グループを使用し、先頭に"*"を付加してRemoteQMを含む3つのキューマネージャー全てに接続可能にします。
クライアントから実行するコマンド・ラインは下記です。
MQCNO_RECONNECTを指定して、接続の異常が検出された場合、同じキューマネージャー・グループの他のキューマネージャーに接続させます。
また、規定のイベント・ハンドラーを呼び出すように指示します。
このコマンドでは、MQCONN()は最初に1回のみ呼び出され、MQPUT()を1秒間隔で100回繰り返します。
mqpgfc -qm "*SampleQM" -q LQ1 -m test -tr -n 100 -i 1000 -cf EventHandler -op MQOP_REGISTER MQCBT_EVENT_HANDLER MQCNO_RECONNECT
*オプションの説明
-cf EventHandler: コールバック関数としてmqpgf/mqpgfc規定のイベント・ハンドラーを指定
-op MQOP_REGISTER: MQCB.OperationにMQOP_REGISTERを設定
MQCBT_EVENT_HANDLER: MQCBD.CallbackTypeにMQCBT_EVENT_HANDLERを設定
MQCNO_RECONNECT: MQCNO.OptionsにMQCNO_RECONNECTを指定
それでは、Server1のSampleQM、Server2のSampleQM、Server1のRemoteQMを全て起動した状態にして、コマンドを実行開始します。 順番に、Server1のSampleQM、Server2のSampleQM、Server1のRemoteQMを落とし、サーバー側ではmqpcfの"con"コマンドでどのキューマネージャーに再接続されているかを確認していきます。 最後にServer2のSampleQMを起動し、正常に接続されることを確認します。 接続をなくす方法はLANケーブルを抜くなど、任意ですが、endmqmを引数無しで実行しても、クライアント自動再接続は有効にならないことに注意してください。 endmqmでキューマネージャーを終了する場合は"-r"オプションを指定すると、クライアントの再接続の試行が行われます。 今回は、この方法を使用してみます。
>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
....
Server1のSampleQMに接続されていることを確認後、"-r"オプションでServer1のSampleQMを停止させます。
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
....
Server2のSampleQMに接続されていることを確認後、"-r"オプションでServer2のSampleQMを停止させます。
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
....
Server1のRemoteQMに接続されていることを確認後、"-r"オプションでServer1のRemoteQMを停止させます。
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)
....
"SampleQM"キューマネージャー・グループのメンバーが全て停止したため、クライアントはリトライを繰り返します。
このリトライの間隔は徐々に長くなります。
※今回のテストでは、endmqm -rでキューマネージャーを停止すると、2回目から数回リトライ間隔が0msと返されています。
最後にServer2のSampleQMを起動します。
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
....
Server2のSampleQMに接続されていることを確認します。
Server2: mqpcf con -qm SampleQM -t APPLTAG |grep mqpgfc
[18/10/16 13:34:47.583089] 48: CONN(414D514353616D706C65514D202020205BC56A5320001A05) TYPE(ALL) APPLTAG(....\mqpgfc.exe)
接続タイムアウトの変更
mqclient.iniのCHANNELSスタンザのMQReconnectTimeoutパラメータに接続タイムアウトの時間を設定できます。 デフォルトは1800秒(30分)です。 下記の様に設定します。
CHANNELS:
MQReconnectTimeout=120
Ex. 8.7 クライアントの自動再接続のタイムアウト時の挙動
自動再接続タイムアウトを120(2分)にして念のため挙動を確認してみます。 SampleQMグループのキューマネージャーは全て停止している状態です。
>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
....
※ここで全てのキューマネージャーを"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
※再接続が始まってからおよそ2分で再接続が失敗し、MQRC_RECONNECT_FAILED(Reconnection failed)に続いて、MQRC_CONNECTION_BROKEN(Connection Broken)のイベントが発生しています。 その後MQPUT()呼び出しは理由コード 2548 MQRC_RECONNECT_FAILEDが返されています。 mqpgfは理由コードに関わらず必ずMQCLOSE()、MQDISC()を呼び出して終了します。 その為、MQDISC()呼び出し中に再度クライアント自動再接続が発生しています。 実際の業務アプリケーションではこの挙動への考慮が必要です。
[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
最後に、これまでのテストでは確認されませんでしたが、クライアントの自動再接続が有効になっている時に、MQPUT()やMQCMIT()の理由コードにMQRC_CALL_INTERRUPTEDが返される場合があります。 これをアプリケーションが受け取った場合、MQクライアントはメッセージが正常に送信されたかどうかが分からい状況であることを示しています。 この場合、アプリケーション側で、メッセージの再送などの考慮が必要です。