0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Redhat OpenshiftでIBM MQのUniform Clusterを動かす (2)

Last updated at Posted at 2022-10-13

Redhat Openshift上のIBM MQ Uniform Clusterにクライアント接続してみる

前回はUniform Clusterの構成を組んでみました。
今回は元々のUniform Clusterの目的である、クラアント接続を試してみます。

MQでクライアント接続する際の方法は、接続先の情報(チャネル名、IP、PORT)を接続時に与えなければならないのですが、方法としては以下があります。

1)MQSERVER環境変数で指定
2)MQCONNX API発行時にプログラムの中で指定
3)CCDT(CLIENT CHANNEL DEFINITION TABLE)を用いて定義を外に出す

Uniform Cluster環境では自動振り分けのための複数宛先への接続が前提なので、CCDTを用います。

またクラウドの外からの接続になるので、TLS通信が前提となります。
通信のための証明書の設定やルート定義が必要ですが、詳しくはこちらを参照してください。
https://www.ibm.com/docs/ja/ibm-mq/9.2?topic=manager-example-configuring-tls

通信系のセットアップについては復習を兼ね、別途まとめたいと思います。

1.CCDTてなんだっけ?

CCDT(CLIENT CHANNEL DEFINITION TABLE)ではMQCLIENTからキュー・マネージャー接続先を指定する定義ファイルです。 Uniform Cluserの構成では、複数のキュー・マネージャーへの接続先の定義を実施する事で、自動切替が可能となっています。

2.CCDTの構成方法

MQ V9.1.2からJSON形式もサポートされるようになりました。
それ以前はrunmqscコマンドを用いて生成する必要があり、また生成したファイルはバイナリ形式のため、そのまま根性だけでは読むのが難しい。。。
そこで今回はJSON形式で作成してみます。

(runmqscではパラメーター名などのSyntaxは定義時にチェックしてくれます。 JSONだとccdt_schema.jsonが提供されていて、これでチェック)

3.CCDTの構成について

1)構成の組合せイメージ

UNIFORMクラスター構成では、接続する全てのキュー・マネージャー向けの定義x呼び出し方式の組合せで構成します。
呼び出し方式は、クラスター名とキュー・マネージャー名の2種類を準備します。
今回は接続先が2つのため、都合2x2 = 4種のエントリーを定義することになります。 イメージ的には以下のようになります。

CCDT定義イメージ
1.QMGR1向けCLUSTER名での接続定義
2.QMGR2向けCLUSTER名での接続定義
3.QMGR1向けキュー・マネージャー名での接続定義
4.QMGR2向けキュー・マネージャー名での接続定義

2)実際の定義

実際の定義体はこちらになります。 前回同様キュー・マネージャー名の一部を"xxxx"としているのは心眼で読む事で見逃していただきたく。。。。
(最初からxxxxで作ってもよかったです)

{
 "channel":
 [
   {
     "name":"CL.OCQMxxxxFR2", 
     "connectionManagement":
      {
        "sharingConversations": 1,
        "clientWeight": 1,
        "affinity": "none",
        "defaultReconnect": "yes",
        "disconnectInterval": 6000,
        "heartbeatInterval": 30,
        "keepAliveInterval": -1
      },
     "clientConnection":
      {
       "connection":
       [
        {
          "host":"FR2向けの外部接続IP",
          "port":443
        }
       ],
        "queueManager":"CLUST1"
      },
      "transmissionSecurity":
      {
      "cipherSpecification":"TLS_RSA_WITH_AES_128_CBC_SHA256"
      },
      "type":"clientConnection"
   },
   {
     "name":"CL.OCQMxxxxFR1", 
     "connectionManagement":
      {
        "sharingConversations": 1,
        "clientWeight": 1,
        "affinity": "none",
        "defaultReconnect": "yes",
        "disconnectInterval": 6000,
        "heartbeatInterval": 30,
        "keepAliveInterval": -1
      },
     "clientConnection":
      {
       "connection":
       [
        {
          "host":"FR1向けの外部接続情報",
          "port":443
        }
       ],
        "queueManager":"CLUST1"
      },
      "transmissionSecurity":
      {
      "cipherSpecification":"TLS_RSA_WITH_AES_128_CBC_SHA256"
      },
      "type":"clientConnection"
   },
   {
     "name":"CL.OCQMxxxxFR2", 
     "connectionManagement":
      {
        "sharingConversations": 1,
        "clientWeight": 1,
        "affinity": "none",
        "defaultReconnect": "yes",
        "disconnectInterval": 6000,
        "heartbeatInterval": 30,
        "keepAliveInterval": -1
      },
     "clientConnection":
      {
       "connection":
       [
        {
          "host":"FR2向けの外部接続情報",
          "port":443
        }
       ],
        "queueManager":"OCQMxxxxFR2"
      },
      "transmissionSecurity":
      {
      "cipherSpecification":"TLS_RSA_WITH_AES_128_CBC_SHA256"
      },
      "type":"clientConnection"
   },
   {
     "name":"CL.OCQMxxxxFR1", 
     "connectionManagement":
      {
        "sharingConversations": 1,
        "clientWeight": 1,
        "affinity": "none",
        "defaultReconnect": "yes",
        "disconnectInterval": 6000,
        "heartbeatInterval": 30,
        "keepAliveInterval": -1
      },
     "clientConnection":
      {
       "connection":
       [
        {
          "host":"FR1向けの外部接続情報",
          "port":443
        }
       ],
        "queueManager":"OCQMxxxxFR1"
      },
      "transmissionSecurity":
      {
      "cipherSpecification":"TLS_RSA_WITH_AES_128_CBC_SHA256"
      },
      "type":"clientConnection"
   }
  ]
}

定義内のhost:では、それぞれのPodに向けたクラウド外部からの接続定義を指定します。

詳細はこちら:https://www.ibm.com/docs/ja/ibm-mq/9.2?topic=dcqmumo-configuring-route-connect-queue-manager-from-outside-red-hat-openshift-cluster

ここではFR1・FR2に向けて、クラスター名とキュー・マネージャー名での接続をそれぞれ準備しています。
(チャネル名はFR1/FR2向けで分けていますが、同じでもいけるはず)

CCDTではCHLTYPE(CLNTCONN)に該当する定義を行っていますので、対向するキュー・マネージャー側ではCHLTYPE(SVRCONN)の定義が必要です。 FR1側では以下の定義をおこなっています。 FR2側も同様に必要です。

dis chl(CL.OCQMxxxxFR1) ALL
     2 : dis chl(CL.OCQMxxxxFR1) ALL
AMQ8414I: Display Channel details.
   CHANNEL(CL.OCQMxxxxFR1)                 CHLTYPE(SVRCONN)
   ALTDATE(2021-12-17)                     ALTTIME(05.29.16)
   CERTLABL( )                             COMPHDR(NONE)
   COMPMSG(NONE)                           DESCR( )
   DISCINT(0)                              HBINT(10)
   KAINT(AUTO)                             MAXINST(999999999)
   MAXINSTC(999999999)                     MAXMSGL(4194304)
   MCAUSER( )                              MONCHL(QMGR)
   RCVDATA( )                              RCVEXIT( )
   SCYDATA( )                              SCYEXIT( )
   SENDDATA( )                             SENDEXIT( )
   SHARECNV(10)                            SSLCAUTH(OPTIONAL)
   SSLCIPH(TLS_RSA_WITH_AES_128_CBC_SHA256)
   SSLPEER( )                              TRPTYPE(TCP)

HBINTはMQチャネルのハートビート(対向する相手の状況監視)の時間を指定します。
CCDT内の"heartbeatInterval"、SVRCONNチャネル定義のHBINTが該当します。
最初WireSharkで見ていたら、再接続が一定間隔で行われていました。
どうも50秒Idleが続くと、接続が切られてしまうようで、Deault 300秒だとIdleと見なされ切断して、でもRECONNECT指定しているから接続して。。。というのを繰り返していました。
そのため50秒未満を指定しています。 HBINTはCLNTCONN/SVRCONN両方で指定した時間の長い方が使われるので、両方変更が必要です。 今回は30 vs 10 なので30になっているはず。 (普通は合わせます)

CipherSpecification(SSLCIPH)も双方で合わせておく必要があります。 またクライアント認証(SSLCAUTH)は"OPTIONAL"なので実行されません。

3)プログラム側

RECONNECTオプションを指定しています。 Cだとこんな感じです。
(CCDTでも指定できるので、一方だけでもよいかも)

connopts.Options += MQCNO_RECONNECT;
  MQCONNX(QMName,               /* queue manager                 */
      &connopts,
      &Hcon,                   /* connection handle              */
      &CompCode,               /* completion code                */
      &CReason);               /* reason code                    */

4.実行準備

プログラムの実行準備として以下の環境変数を設定しています。

MQCHLLIB= CCDTの保管ディレクトリ
MQCHLTAB= CCDTファイル名
MQSSLKEYR= TLS用のKEYDB指定
MQCCSID= クライアント側の文字コード、QMGR側と合わせてますが相互に変換可能だと不要(のはず)

5.接続と切替指示

クライアントアプリケーションを起動し、Uniform Clusterに接続してみます。 接続先のQMNameはクラスター名に"*"を先頭に付けた、”*CLUST1"を指定します。
"putreconc.exe"が今回使用しているWindows PCでのクライアントアプリです。
接続先はCCDTのCLNTWGHT値の比率でランダムに選択され、今回はたまたまFR1側に接続。

dis apstatus(*) TYPE(QMGR)
     6 : dis apstatus(*) TYPE(QMGR)
AMQ8932I: Display application status details.
    APPLNAME(rojects\mqsamp\putreconc.exe)
    ACTIVE(YES)                             COUNT(1) 
    MOVCOUNT(1)                             BALSTATE(OK)
    LMSGDATE(2021-12-17)                    LMSGTIME(05.30.42)
    QMNAME(OCQMxxxxFR1)                 
    QMID(OCQMxxxxFR1_2021-12-15_01.23.12)
    TYPE(QMGR)                           
AMQ8932I: Display application status details.
    APPLNAME(rojects\mqsamp\putreconc.exe)
    ACTIVE(YES)                             COUNT(0) 
    MOVCOUNT(0)                             BALSTATE(LOW)
    LMSGDATE(2021-12-17)                    LMSGTIME(05.29.45)
    QMNAME(OCQMxxxxFR2)                 
    QMID(OCQMxxxxFR2_2021-10-05_12.21.46)
    TYPE(QMGR)   

ここでFR1側をSUSPENDしてみます。
そうすると接続先がFR1からFR2に移っています。

suspend qmgr CLUSTER(CLUST1) 
     8 : suspend qmgr CLUSTER(CLUST1) 
AMQ8557I: SUSPEND QUEUE MANAGER accepted.
dis apstatus(*) type(QMGR)
     9 : dis apstatus(*) type(QMGR)
AMQ8932I: Display application status details.
  APPLNAME(rojects\mqsamp\putreconc.exe)
   ACTIVE(YES)                             COUNT(0) 
   MOVCOUNT(0)                             BALSTATE(OK)
   LMSGDATE(2021-12-17)                    LMSGTIME(05.31.56)
   QMNAME(OCQMxxxxFR1)                 
   QMID(OCQMxxxxFR1_2021-12-15_01.23.12)
   TYPE(QMGR)                           
AMQ8932I: Display application status details.
   APPLNAME(rojects\mqsamp\putreconc.exe)
   ACTIVE(YES)                             COUNT(1) 
   MOVCOUNT(1)                             BALSTATE(OK)
   LMSGDATE(2021-12-17)                    LMSGTIME(05.31.55)
   QMNAME(OCQMxxxxFR2)                 
   QMID(OCQMxxxxFR2_2021-10-05_12.21.46)
   TYPE(QMGR)                           

FR2側で確認すると以下になっています。

dis chs(CL*)
    15 : dis chs(CL*)
AMQ8417I: Display Channel Status details.
   CHANNEL(CL.OCQMxxxxFR2)                CHLTYPE(SVRCONN)
   CONNAME(172.17.45.14)                   CURRENT
   STATUS(RUNNING)                         SUBSTATE(RECEIVE)
dis apstatus(*) type(QMGR) 
    16 : dis apstatus(*) type(QMGR) 
AMQ8932I: Display application status details.
    APPLNAME(rojects\mqsamp\putreconc.exe)
    ACTIVE(YES)                             COUNT(1) 
    MOVCOUNT(1)                             BALSTATE(OK)
    LMSGDATE(2021-12-17)                    LMSGTIME(05.31.29)
    QMNAME(OCQMxxxxFR2)                 
    QMID(OCQMxxxxFR2_2021-10-05_12.21.46)
    TYPE(QMGR)    
(FR1側表示は省略)                       

なおSuspend状態は”DIS CLUSQMGR”コマンドのSUSPENDで確認できます。

dis clusqmgr(*) QMTYPE SUSPEND
    10 : dis clusqmgr(*) QMTYPE SUSPEND
AMQ8441I: Display Cluster Queue Manager details.
   CLUSQMGR(OCQMxxxxFR1)                  CHANNEL(TO.FR1)
   CLUSTER(CLUST1)                         QMTYPE(REPOS)
   SUSPEND(YES)                         
AMQ8441I: Display Cluster Queue Manager details.
   CLUSQMGR(OCQMxxxxFR2)                  CHANNEL(TO.FR2)
   CLUSTER(CLUST1)                         QMTYPE(REPOS)
   SUSPEND(NO)        

最近のWiresharkはMQのプロトコルやTLSで暗号化された通信も秘密鍵があれば、解析できます。
(自分でテスト用に作成した秘密鍵なので自由に使っていますが、本当の利用環境では証明書は厳重に管理する必要があります)

今回は、自動再接続を利用したUniform Clusterの動的接続先の切替を見てみましたが、Wiresharkで見ていると、なかなか面白かったです。
ただ、アプリケーションの知らないところで勝手に切り替わってよいのか? という疑問もあります。 ここらはMQ 9.2.4(CD版)でクライアントアプリからの制御オプションもあるようです。 次回の課題ですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?