MQ选型及RocketMQ简介

1,021 阅读3分钟

消息队列对比参照表

RocketMQ 4.5.1安装教程

一、下载

前往 http://rocketmq.apache.org/release_notes/release-notes-4.5.1/ ,下载 Binary 文件即可。

二、系统要求

  • 64位操作系统,生产环境建议Linux/Unix/MacOS(Windows操作系统安装说明详见 Windows操作系统安装教程)
  • 64位JDK 1.8(目前RocketMQ不支持 JDK 11)
  • 4G+的可用磁盘

三、Linux/Unix/MacOS安装教程

3.1 搭建

  • 解压压缩包
unzip rocketmq-all-4.5.1-bin-release.zip
  • 切换目录到RocketMQ根目录
cd rocketmq-all-4.5.1-bin-release
  • 启动Name Server
nohup sh bin/mqnamesrv &

验证是否启动OK:

tail -f ~/logs/rocketmqlogs/namesrv.log

# 如果成功启动,能看到类似如下的日志:
2019-07-18 17:03:56 INFO main - The Name Server boot success. ...
  • 启动 Broker
nohup sh bin/mqbroker -n localhost:9876 &

验证是否启动OK:

tail -f ~/logs/rocketmqlogs/broker.log

# 如果启动成功,能看到类似如下的日志:
2019-07-18 17:08:41 INFO main - The broker[local, 192.168.43.197:10911] boot success. serializeType=JSON and name server is localhost:9876

3.2 验证RocketMQ功能正常(可选)

3.2.1 验证生产消息正常

执行如下命令:

export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

能看到类似如下输出:

SendResult [sendStatus=SEND_OK, msgId=C0A82BC5F36C511D50C05B41...
3.2.2 验证消费消息正常

执行如下命令:

sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

能看到类似如下输出:

ConsumeMessageThread_4 Receive New Messages: [MessageExt [queueId=3, stor....

3.3 停止

依次执行以下两条命令即可

# 命令
sh bin/mqshutdown broker
# 输出如下信息说明停止成功
The mqbroker(36695) is running...
Send shutdown request to mqbroker(36695) OK

# 命令
sh bin/mqshutdown namesrv
# 输出如下信息说明停止成功
The mqnamesrv(36664) is running...
Send shutdown request to mqnamesrv(36664) OK

四、Windows操作系统安装教程

www.jianshu.com/p/4a275e779…

五、生产可用集群搭建教程

www.itmuch.com/books/rocke…

RocketMQ控制台安装教程

一、下载代码

# 方式一、git下载,执行如下命令
git clone https://github.com/apache/rocketmq-externals.git

# 方式二、直接下载,访问如下地址即可
https://github.com/apache/rocketmq-externals/archive/master.zip

二、修改控制台代码

2.1 修改配置

找到rocketmq-console/src/main/resources/application.properties 根据需求,修改配置

# 管理后台访问上下文路径,默认为空
# 如果填写,需写成/xxx的形式,例如/console
server.contextPath=

# 控制台的端口
server.port=8080

...

# if this value is empty,use env value rocketmq.config.namesrvAddr  NAMESRV_ADDR | now, you can set it in ops page.default localhost:9876
# Name Server地址
rocketmq.config.namesrvAddr=

# if you use rocketmq version < 3.5.8, rocketmq.config.isVIPChannel should be false.default true
rocketmq.config.isVIPChannel=

#rocketmq-console's data path:dashboard/monitor
rocketmq.config.dataPath=/tmp/rocketmq-console/data

#set it false if you don't want use dashboard.default true
rocketmq.config.enableDashBoardCollect=true

#set the message track trace topic if you don't want use the default one
rocketmq.config.msgTrackTopicName=

rocketmq.config.ticketKey=ticket

#Must create userInfo file: ${rocketmq.config.dataPath}/users.properties if the login is required
rocketmq.config.loginRequired=false

笔者只修改了如下两项:

# console端口
server.port=17890
# name server地址
# 也可以不修改,在启动完console后,在控制台导航栏 - 运维 - NameSvrAddrList一栏设置
rocketmq.config.namesrvAddr=localhost:9876

2.2 修改依赖

修改 pom.xml ,修改RocketMQ相关依赖的版本

找到

<rocketmq.version>4.4.0</rocketmq.version>

修改为

<rocketmq.version>你的RocketMQ版本</rocketmq.version>

笔者使用的是RocketMQ 4.5.1,故而改为

<rocketmq.version>4.5.1</rocketmq.version>

2.3 修改代码

修改pom.xml后,org.apache.rocketmq.console.service.impl.MessageServiceImpl#queryMessageByTopic编译会报错,所以需要解决一下。将

DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(MixAll.TOOLS_CONSUMER_GROUP, null);

改为:

RPCHook rpcHook = null;
DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(MixAll.TOOLS_CONSUMER_GROUP, rpcHook);

即可。

2.4 打包构建

# 切换到代码根目录
cd rocketmq-externals

# 切换到控制台目录
cd rocketmq-console

# 构建
mvn clean package -DskipTests

三、懒人包

下载地址:https://github.com/eacdy/rocketmq-externals/releases

四、启动

java -jar rocketmq-console-ng-1.0.1.jar

五、访问

访问 http://localhost:17890 (端口用上面 application.properties 中的 server.port=17890 指定,默认是8080) ,即可看到类似如下的界面:

六、控制台使用说明

github.com/eacdy/rocke…

Springboot 2.x 整合rocketmq-spring-boot-starter

一、导入maven依赖

<dependency>
  <groupId>org.apache.rocketmq</groupId>
  <artifactId>rocketmq-spring-boot-starter</artifactId>
  <version>2.0.3</version>  // 2.0.3内置的rocketmq版本是4.5.1,其他版本要注意相应的匹配
</dependency>

二、yml 配置

生产者配置:

rocketmq:
  name-server: 127.0.0.1:9876 #rocketmq服务地址
  producer:
    group: rocketmq_test #自定义的组名称,必须指定group
    send-message-timeout: 3000  #消息发送超时时长

消费者配置:

rocketmq:
  name-server: 127.0.0.1:9876 #rocketmq服务地址

配置生产者消息发送工具类:

@Slf4j
@Component
public class SpringProducer
{
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    public void sendMsg(String topic, String msg)
    {
        log.info("发送报文:" + msg);
        this.rocketMQTemplate.convertAndSend(topic, msg);
    } 
}

配置消费者进行消息处理:

@Slf4j
@Component
@RocketMQMessageListener(topic = "${rocketmq.producer.topic}", consumerGroup = "${rocketmq.producer.group}") 
// 生产者group是放在配置文件,consumer的group是放在这里的
public class SpringConsumer implements RocketMQListener<String>
{
    @Override
    public void onMessage(String msg)
    {
        log.info("收到消息:" + msg);
    }
}

注: 生产者编写--如果是Rocketmq就用 RocketMQTemplate, 如果用的是Kafka, 就用 KafkaTemplate, 如果是RabbitMQ 就用 AmqpTemplate; 消费者编写--RoctetMQ:RoctMQMessageListener,ActiveMQ/Artemis:JmsListener, RabbitMQ:RabbitListener,Kafka:KafkaListener

RocketMQ事务型消息

执行原理

事务消息的三态:

  • commit: 提交事务消息,消费者可以消费此消息
  • Rollback: 回滚事务消息,broker会删除该消息,消费者不能消费
  • UNKNOWN: broker需要回查确认该消息的状态

编码实现

生产者

@Component
public class SpringTransactionProducer {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送消息
     *
     * @param topic
     * @param msg
     */
    public void sendMsg(String topic, String msg) {
        Message message = MessageBuilder.withPayload(msg).
        .setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
        build();
        // myTransactionGroup要和@RocketMQTransactionListener(txProducerGroup = "myTransactionGroup")定义的一致
        this.rocketMQTemplate.sendMessageInTransaction("myTransactionGroup",topic,message, null);
        System.out.println("发送消息成功");
    }
}

消费者

@Component
@RocketMQMessageListener(topic = "spring-tx-my-topic", // 与生产者topic保持一致
                            consumerGroup = "tx-consumer")
public class SpringTxConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String msg) {
        System.out.println("接收到消息 -> " + msg);
    }
}

本地事务监听

@RocketMQTransactionListener(txProducerGroup = "myTransactionGroup") // 与生产者事务组保持一致
public class TransactionListenerImpl implements RocketMQLocalTransactionListener {

    private static Map<String, RocketMQLocalTransactionState> STATE_MAP = new HashMap<>();

    /**
     *  执行业务逻辑
     *
     * @param message
     * @param o
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        String transId = (String)message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);

        try {
            System.out.println("执行操作");
            Thread.sleep(500);
            // 设置事务状态
            STATE_MAP.put(transId, RocketMQLocalTransactionState.COMMIT);
            // 返回事务状态给生产者
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            e.printStackTrace();
        }

        STATE_MAP.put(transId, RocketMQLocalTransactionState.ROLLBACK);
        return RocketMQLocalTransactionState.ROLLBACK;

    }

    /**
     * 回查
     *
     * @param message
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        String transId = (String)message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
        System.out.println("回查消息 -> transId = " + transId + ", state = " + STATE_MAP.get(transId));
        return STATE_MAP.get(transId);
    }
}