首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

WebSphere MQ 基礎與 Java 客戶端收發消息實戰

     編輯:Java 相關知識

IBM WebSphere MQ (現 IBM MQ) 是企業級消息中間件標桿,提供可靠、異步、跨平台的消息傳遞能力。本文解析核心概念、通信機制,並給出生產級 Java 客戶端收發消息完整代碼。

核心概念體系

概念說明類比
Message (消息)數據載體,包含應用數據 + 描述符(Message Descriptor: ID、類型、優先級、過期時間)信封裡的信件
Queue (隊列)消息緩存容器,FIFO 順序存儲,支援持久化郵筒
Queue Manager (隊列管理器)MQ 運行時核心進程,管理隊列、通道、事務、持久化郵局
Channel (通道)隊列管理器間通信路徑,傳輸消息郵路
MQI (Message Queue Interface)C/Java 等語言調用的標準 API郵政業務接口

MQ 運行時架構

消息傳遞模式

  • 點對點:發送者 → 隊列 → 接收者 (單消費者)
  • 發布/訂閱:發布者 → 主題 → 多訂閱者 (MQ V5.3+ 支援)

異步特性:發送者無需等待接收者處理,消息持久化存儲於隊列,即使接收端離線也不丟失。

消息與隊列交互

JMS vs 原生 MQI

  • JMS:J2EE 標準 API,屏蔽底層中間件差異,可移植性強
  • MQI (com.ibm.mq.*):IBM 專有 API,功能更全、性能略高、支援 MQ 獨有特性

本文採用原生 MQI 演示底層控制力。

Java 發送消息完整實現

package com.example.mq;

import com.ibm.mq.*;
import com.ibm.mq.constants.MQConstants;

public class MqMessageSender {

    private static final String HOST = "192.168.1.18";
    private static final int PORT = 1414;  // 默認監聽端口
    private static final String CHANNEL = "CHANNEL1";
    private static final String QM_NAME = "QM_SERVER";
    private static final String QUEUE_NAME = "INITQ";
    private static final int CCSID = 1381;  // 簡體中文 GBK/GB18030

    public void sendMessages(int count) {
        MQQueueManager qMgr = null;
        MQQueue queue = null;
        try {
            // 1. 設置連接環境
            MQEnvironment.hostname = HOST;
            MQEnvironment.port = PORT;
            MQEnvironment.channel = CHANNEL;
            MQEnvironment.CCSID = CCSID;
            // MQEnvironment.userId = "mqm";  // 若需認證
            // MQEnvironment.password = "password";

            // 2. 連接隊列管理器
            qMgr = new MQQueueManager(QM_NAME);
            System.out.println("連接隊列管理器成功: " + QM_NAME);

            // 3. 打開隊列 (輸出/查詢權限)
            int openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_INQUIRE;
            queue = qMgr.accessQueue(QUEUE_NAME, openOptions);
            System.out.println("打開隊列成功: " + QUEUE_NAME);

            // 4. 構建消息
            MQMessage message = new MQMessage();
            message.format = MQConstants.MQFMT_STRING;
            message.characterSet = CCSID;
            message.writeString("這是測試消息 - " + System.currentTimeMillis());
            message.expiry = MQConstants.MQEI_UNLIMITED;  // 永不過期

            // 5. 發送選項
            MQPutMessageOptions pmo = new MQPutMessageOptions();
            pmo.options = MQConstants.MQPMO_SYNCPOINT;  // 事務性發送 (可選)

            // 6. 批量發送
            for (int i = 1; i <= count; i++) {
                message.writeString("批次消息 #" + i + " @ " + new java.util.Date());
                message.messageId = MQConstants.MQMI_NONE;  // 讓 MQ 自動生成 MsgId
                message.correlationId = MQConstants.MQCI_NONE;
                queue.put(message, pmo);
                System.out.println("發送第 " + i + " 條消息成功");
            }

        } catch (MQException mqe) {
            System.err.println("MQ 錯誤: CC=" + mqe.completionCode + " RC=" + mqe.reasonCode);
            mqe.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 7. 資源釋放 (逆序關閉)
            closeQuietly(queue);
            disconnectQuietly(qMgr);
        }
    }

    private void closeQuietly(MQQueue queue) {
        if (queue != null && queue.isOpen()) {
            try { queue.close(); } catch (MQException ignored) {}
        }
    }

    private void disconnectQuietly(MQQueueManager qMgr) {
        if (qMgr != null && qMgr.isConnected()) {
            try { qMgr.disconnect(); } catch (MQException ignored) {}
        }
    }

    public static void main(String[] args) {
        new MqMessageSender().sendMessages(5);
    }
}

程序運行結果

Java 接收消息實現要點

public void receiveMessages() {
    // ... 連接、打開隊列 (MQOO_INPUT_AS_Q_DEF | MQOO_INQUIRE)
    MQGetMessageOptions gmo = new MQGetMessageOptions();
    gmo.options = MQConstants.MQGMO_WAIT | MQConstants.MQGMO_SYNCPOINT;
    gmo.waitInterval = 5000;  // 等待 5 秒

    while (running) {
        MQMessage msg = new MQMessage();
        try {
            queue.get(msg, gmo);  // 阻塞等待消息
            String text = msg.readStringOfByteLength(msg.getMessageLength());
            System.out.println("收到消息: " + text);
            // 業務處理...
            qMgr.commit();  // 事務提交確認消費
        } catch (MQException mqe) {
            if (mqe.reasonCode == MQConstants.MQRC_NO_MSG_AVAILABLE) {
                continue;  // 超時無消息,繼續等待
            }
            // 其他錯誤處理
        }
    }
}

生產環境關鍵配置優化

維度建議
連接管理使用連接池 (如 Spring MQQueueConnectionFactory + PooledConnectionFactory)
事務控制本地事務 MQPMO_SYNCPOINT/MQGMO_SYNCPOINT;分布式事務接入 JTA
消息持久化發送端 message.persistence = MQPER_PERSISTENT,隊列定義 DEFPERSIST(YES)
編碼統一全鏈路指定 CCSID (如 1381/5488/1200),避免跨平台亂碼
錯誤重試指數退避重試 + 死信隊列 (DLQ) 配置
監控指標隊列深度、消息延遲、連接數、錯誤率

MQ 核心優勢總結

  • 可靠性:持久化 + 事務 + 確認機制,零消息丟失
  • 解耦:生產者/消費者無需同時在線、無需知曉彼此位置
  • 異步削峰:流量洪峰緩衝,保護下游系統
  • 跨平台:Mainframe、分佈式、雲原生統一互通
  • 企業級特性:集群、高可用、安全審計、消息審計

掌握 MQ 核心模型與 Java 客戶端編程,即可構建高可靠的企業集成總線骨幹。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved