【IBM MQ相关】IBM MQ介绍以及通过docker安装、与Spring Boot集成

2,108 阅读5分钟

【本文内容】

  • MQ介绍
  • 介绍IBM MQ messaging模型
  • 通过docker安装IBM MQ
  • IBM MQ Console介绍
  • 【Java代码示例】使用JMSIBM MQ集成(Spring Boot

1. Message Queue vs Restful APIs

参考:www.youtube.com/watch?v=ynj…

消息队列(Message Queue)是为了解决数据的发送问题,从一端到送到另一端。

那么为什么不用Restful APIs? 技术上当然也可以这么实现:

  • 一般情况下用Restful APIs调用是同步的,如果app1产生的数据过快,作为消费端的app2无法应对,那么会造成app2系统的奔溃。
  • 并且相互侵入的代码较多,如果有很多app相互调用的话,就会变的相对复杂。
  • 或许还要解决app之间调用的security问题。

如果使用MQ来实现:

  • 那么消息的发送是异步的,如果app1产生的数据过快,作为消费端的app2也可以按照自己的速度消费。
  • app之间可以解耦,发送方只需要负责将数据发送到Broker中,消费方只需要监听Broker的消息。app1和2之间并不需要直接产生连接。

IBM MQ提供了以下功能:

  • Communication
  • Security
  • Transactions
  • Persistence
  • Scale
  • Recovery

2. 介绍IBM MQ messaging模型

参考:www.youtube.com/watch?v=U03…

  • putting and getting messages
  • point-to-point messaging
  • publish-subscribe (event-driven messaging)
  • request-response messaging
  • message expiry
2.1 putting and getting messages

在IBM MQ中,发送消息,通常跟Queues, Topics有关。

2.2 端到端的消息发送

适用的场景如,我们想要往数据库存放数据,如果同一时间有海量的数据存入,可能会导致数据库崩溃,这时候我们可以先把数据放到IBM MQ的Queue中,然后数据库一条一条的消费,再存入。

2.3 publish-subscribe (event-driven messaging)

订阅模式,即生产者往IBM MQ的Topic中发送消费,那么所有订阅了该Topic的消费端(可能很多个)都能收到消息。

2.4 request-response messaging

生产者在发送消息的时候,渴望消费端在消费完消息后再通知生产者。 这时候会有一个临时的queue,消费端在消费完后往这个临时的queue中发送回执。 image.png

比如一个售票的app,在接到客户的买票请求后,从航空公司下订单并支付,这时候航空公司可以将票作为回执。进来app再将票返回给客户。【这个场景有点像同步的Restful API调用】

2.5 message expiry

消息是有时间限制的,在Queue中未被消费的过期消息,将无法再被消费。

3. 通过docker安装IBM MQ

参考:www.youtube.com/watch?v=xBX…
Docker hub:hub.docker.com/r/ibmcom/mq

3.1 拉取最新版本的镜像

docker pull ibmcom/mq:latest

下载好后,可以通过docker images查看镜像: image.png

3.2 创建docker volume

创建volume是为了将数据持久化到本地磁盘,以便ibm mq在重启后数据不丢失。 为啥叫qm1data,是因为我们要创建的queue manager就叫qm1

docker volume create qm1data

image.png

3.3 启动容器

docker run --env LICENSE=accept --env MQ_QMGR_NAME=QM1 --volume qm1data:/mnt/mqm --publish 1414:1414 --publish 9443:9443 --detach --env MQ_APP_PASSWORD=passw0rd ibmcom/mq:latest

  • LICENSE=accept表示在容器内我们accept mq的license
  • MQ_QMGR_NAME=QM1表示我们创建了一个MQ Server/或叫queue manager,名称为QM1
  • volume:我们把容器内的目录/mnt/mqm目录印射到volume=qm1data上
  • 1414端口为应用程序通过该端口连接到ibm mq上,因为app可能在本地,所以用-p暴露出来,以便可以在本地连到docker的ibm mq中。
  • 9443端口为ibm mq console
  • detach表示在后台运行
  • MQ_APP_PASSWORD表示app连接到mq的时候需要通过这个密码

image.png

可以通过docker ps查看: image.png

3.4 进入容器内部以进行测试

以bath shell的方式进入容器内进行交互:

docker exec -it 22581b03a450 bash

image.png

开始测试:

3.4.1 显示版本:display my mq version

dspmqver

可以看到版本为9.2.4.0,运行的License类型为Developer: image.png

3.4.2 查看mq server/mq manager:display mq

dspmq

可以看到我们有一个queue manager,即上述创建的名字叫:MQ1。 image.png

4. Console

参考:

我们在#3中通过docker启动ibm mq的时候,同时也对外暴露了console的端口:9443,所以可以直接访问:https://localhost:9443/ibmmq/console/login.html

image.png

默认的用户名密码:

  • User:  admin
  • Password:  passw0rd

在本地队列管理器中可以看到我们创建的QM1

image.png

IBM MQ会默认创建以下Queue,当然我们也可以点击【创建】按纽自行创建: image.png

5. Java代码示例:使用JMS与IBM MQ集成

参考:developer.ibm.com/tutorials/m…

JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。(参考:JMS解析(一)——JMS简介

5.1 加上MQ Spring Starter

a. 首先是依赖:

  • spring-boot-starter-web是Spring Boot的依赖。
  • mq-jms-spring-boot-starter是Spring Boot与mq-jms的集成,IBM MQ的操作等需要这个jar。
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.7</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.ibm.mq</groupId>
        <artifactId>mq-jms-spring-boot-starter</artifactId>
        <version>2.0.0</version>
    </dependency>
</dependencies>

b. 在resource下加上IBM MQ的配置
application.properties中加上以下内容:

ibm.mq.queueManager=QM1
ibm.mq.channel=DEV.ADMIN.SVRCONN
ibm.mq.connName=localhost(1414)
ibm.mq.user=admin
ibm.mq.password=passw0rd

c. Spring Boot的入口类:
除了@SpringBootApplication这个主要的注解外,还需要加上@EnableJms注解,这个注解会帮忙发现注解@JmsListener

@SpringBootApplication
@EnableJms
public class IBMMQApplication {

    public static void main(String[] args) {
        SpringApplication.run(IBMMQApplication.class, args);
    }
}
5.2 通过JmsTemplate向IBM MQ发送消息

IBM MQ Spring Boot Starter会基于上述的application.properties创建JmsTemplate,可以通过@Autowired引入。

我们往默认的队列"DEV.QUEUE.1"中发送消息:

@RestController
public class MessageController {

    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping("send")
    public boolean convertAndSend() {
        jmsTemplate.convertAndSend("DEV.QUEUE.1", "Test message, hello ibm mq!");
        return true;
    }

}
5.3 通过@JmsListener接收消息

@JmsListener会默认为我们创建一个JmsListenerContainerFactory,如果想要自定义传入,可通过参数containerFactory传入:

@Component
public class JMSMessageReceiver {
    
    @JmsListener(destination = "DEV.QUEUE.1")
    public void receiveMessage(String data) throws Exception {
        System.out.println("Received <" + data + ">");
    }
    
}

【测试】 在页面上调用:http://localhost:8080/send
后台会接收到消息并打印:Received <Test message, hello ibm mq!>