SpringBoot学习笔记十五:springBoot整合RocketMQ

▼魔方 西西 提交于 2020-01-28 18:10:33

1. SpringBoot学习笔记十五:springBoot整合RocketMQ

1.1. RocketMQ简介

  1. 是阿里巴巴的开源框架
  2. 在高压下1毫秒内响应延迟超过99.6%
  3. 适合金融性业务,高可用的跟踪和审计功能。
  4. 支持发布订阅模型,和点对点模式
  5. 支持拉pull和推push两种消息模式
  6. 单一队列百万消息
  7. 支持单master节点,多master节点,多master和slave节点
1.1.1. 概念

Producer:消息生产组

ProducerGroup:消息生产组,发送同类消息的一个消息生产组

Consumer:消费者

ConsumerGroup:消费同一个消息的多个实例

Tag:标签,子主题,用于区分同一个主题下的不同业务的消息。

Topic:主题

Message:消息

Broker:MQ程序,接收生产的消息,提供给消费者消费的程序。

Name Server:给生产者和消费者提供路由信息,提供轻量级的服务发现和路由。

1.2. linux安装rocketMQ

  1. 下载二进制文件binary
  2. 解压二进制文件到/usr/rocketmq路径下
unzip rocketmq-all-4.2.0-bin-release.zip -d /usr/local/rocketmq
  1. 参考安装文档

linux安装rocketMq

  1. 进入解压后的bin目录
    • 表示启动
nohup sh mqnamesrv &
  1. 查看服务名字是否启动成功
查看日志,最后一行显示这个表示启动成功
The Name Server boot success. serializeType=JSON
  1. 启动rocketMq程序
启动broker
nohup sh mqbroker -n 127.0.0.1:9876 &
  1. 可以通过查看java进程查看是否启动成功
ps -ef|grep java
  1. 关闭namesrv和broker执行的命令
sh mqshutdown namesrv
sh mqshutdown broker

1.3. 安装rocketMQ的可视化控制台

  1. 从github下载

rocketMq可视化控制台下载地址

  1. 进入rocketmq-console中执行mvn打包命令(编译)
mvn clean package -Dmaven.test.skip=true
  1. target目录中通过java -jar的方式运行。
  2. 出现无法连接获取broker信息

1)修改配置文件,名称路由地址为namesrvAddr,修改为公网ip+端口号

2)src/main/resource/application.properties处修改

rocketmq.config.namesrvAddr=xxx.xxx.xxx.xxx:9876

  1. 默认访问端口为localhost:8080这个可以修改
  2. 检查防火墙,安全组规则的端口是否开启。

1.4. 阿里云配置RocketMQ(已经安装好jdk8)

  1. 下载rocketMQ二进制文件,将该二进制文件解压到/usr/rocketmq目录下
  2. 修改rocketmq/conf中的broker.conf文档,添加brokerIP1=公网ip,添加namesrvAddr=公网ip:9876
  3. rocketmq占用大量内存,可能要修改内存大小

rocketmq修改启动内存大小

  1. 启动rocketmq的名称服务(路由服务),进入bin目录下
nohup sh mqnamesrv -n 公网ip:9876 &
  1. 在bin目录启动rocketmq的程序服务
    • 注意里面的…/conf,我犯错在这里的相对路径这块。
nohup sh mqbroker -n 公网ip:9876 -c ../conf/broker.conf autoCreateTopicEnable=true &

1.5. SpringBoot2.x整合rocketMq

1.5.1. springBoot2.x开发rocketmq的生产者
  1. application.properties添加配置
#消费者的组名
apache.rocketmq.consumer.pushConsumer=orderConsumer
#生产者的组名
apacha.rocketmq.producer.producerGroup=producer
#NameServer地址
apache.rocketmq.namesrvAddr=xxx.xxx.xxx.xxx:9876
  1. springboot start没有和Rocketmq进行整合,所以在启动项目时要初始化生产者
package net.xdclass.xdclass_springboot.jms;

import javax.annotation.PostConstruct;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.stereotype.Component;
@Component
public class MsgProducer {

    //生产者的组名
    @Value("${apacha.rocketmq.producer.producerGroup}")
    private String producerGroup;

    //地址
    @Value("${apache.rocketmq.namesrvAddr}")
    private String namesrvAddr;

    private DefaultMQProducer producer;

    public String getProducerGroup() {
        return producerGroup;
    }

    public void setProducerGroup(String producerGroup) {
        this.producerGroup = producerGroup;
    }

    public String getNamesrvAddr() {
        return namesrvAddr;
    }

    public void setNamesrvAddr(String namesrvAddr) {
        this.namesrvAddr = namesrvAddr;
    }

    public DefaultMQProducer getProducer() {
        return producer;
    }

    public void setProducer(DefaultMQProducer producer) {
        this.producer = producer;
    }

    @PostConstruct
    public void defaultMQProducer() {
        //生产者的组名
        producer=new DefaultMQProducer(producerGroup);
        //指定NameServer地址,多个地址以;隔开
        //如producer.setNameserAddr("192.168.100.141:9876;192.168.100.142:9876");
        producer.setNamesrvAddr(namesrvAddr);
        producer.setVipChannelEnabled(false);
        try {
            // Producer对象在使用之前必须调用start初始化,并且只能初始化一次。
            producer.start();
        }catch (Exception e) {
            e.printStackTrace();
            // TODO: handle exception
        }
        //producer.shutdown();一般在应用上下文,关闭的时候进行关闭,用上下文监听器。
    }

}

初始化生产者:要指定生产者的组名,路由地址名

  1. 接口调用消息队列生产者,将消息放入broker指定的消息队列中
@Autowired
private MsgProducer msgProducer;
@GetMapping("/order2")
public Object order2(String msg,String tag) throws UnsupportedEncodingException, MQClientException, RemotingException, MQBrokerException, InterruptedException {
    //创建一个消息实例,包含topic tag,和消息体,tag是二级分类
    Message message=new Message("testTopic",tag,msg.getBytes(RemotingHelper.DEFAULT_CHARSET));
    SendResult result =msgProducer.getProducer().send(message);
    System.out.println("发送响应:MSGId:"+result.getMsgId()+",发送状态:"+result.getSendStatus());
    return JsonData.buildSuccess();
}
  1. 可能报错:

DESC: service not available now , maybe disk full ,CL;当磁盘空间达到90%会报这个错

解决方案:修改启动脚本runbroker.sh,在里面增加一句话即可:调整报错空间大小

JAVA_OPT="${JAVA_OPT}-Drocketmq.broker.diskSpaceWarningLevelRatio=0.98“

表示当磁盘空间到达98%时才拒绝接受生产者生产的消息。

1.5.2. springBoot2.x开发消息队列的消费者
  1. 消费处理代码
@Component
public class MsgConsumer {

    //注入路由地址
    //生产者的组名
    @Value("${apacha.rocketmq.producer.producerGroup}")
    private String producerGroup;

    //地址
    @Value("${apache.rocketmq.namesrvAddr}")
    private String namesrvAddr;

    //初始化
    @PostConstruct
    public void defaultMQPushConsumer() {
        DefaultMQPushConsumer consumer =new DefaultMQPushConsumer(producerGroup);
        //指定NameServer地址,多个地址以;隔开
        consumer.setNamesrvAddr(namesrvAddr);
        try {
            //设置consumer所订阅的Topic和Tag *代表全部的tag
            consumer.subscribe("testTopic", "*");
            //配置消费策略
            //CONSUME_FROM_LAST_OFFSET 默认策略,从该队列队尾开始消费,跳过历史消息。
            //CONSUME_FROM_FIRST_OFFSET  从对列最开始开始消费,即历史消息,(还存储在broker里的)全部消费一遍。
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
            //MessageListenerOrderly这个是有序的(创建订单,扣款,通知这是有序的)
            //MessageListenerConcurrently这个是无序的,并行的方式处理,效率高很多。 
            consumer.registerMessageListener((MessageListenerConcurrently)(list,context)->{
                try {
                    for(MessageExt messageExt:list) {
                        System.out.println("messageExt:"+messageExt);//输出消息内容
                        String messageBody=new String(messageExt.getBody(),RemotingHelper.DEFAULT_CHARSET);
                        System.out.println("消费响应:msgId"+messageExt.getMsgId()+", msgBody:"+messageBody);//输出消息内容
                    }
                }catch(Exception e){
                    e.printStackTrace();
                    return ConsumeConcurrentlyStatus.RECONSUME_LATER;//稍后再试
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//消费成功
            });
            consumer.start();
        }catch (Exception e) {
            e.printStackTrace();
            // TODO: handle exception
        }

    }
}

1.6. RocketMQ大致流程

rocketMQ

1.7. 常见问题处理

rocketmq常见问题

rocketmq连接线上服务失败

rocketmq报错解决方案

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!