1. SpringBoot学习笔记十五:springBoot整合RocketMQ
文章目录
1.1. RocketMQ简介
- 是阿里巴巴的开源框架
- 在高压下1毫秒内响应延迟超过99.6%
- 适合金融性业务,高可用的跟踪和审计功能。
- 支持发布订阅模型,和点对点模式
- 支持拉pull和推push两种消息模式
- 单一队列百万消息
- 支持单master节点,多master节点,多master和slave节点
1.1.1. 概念
Producer:消息生产组
ProducerGroup:消息生产组,发送同类消息的一个消息生产组
Consumer:消费者
ConsumerGroup:消费同一个消息的多个实例
Tag:标签,子主题,用于区分同一个主题下的不同业务的消息。
Topic:主题
Message:消息
Broker:MQ程序,接收生产的消息,提供给消费者消费的程序。
Name Server:给生产者和消费者提供路由信息,提供轻量级的服务发现和路由。
1.2. linux安装rocketMQ
- 下载二进制文件binary
- 解压二进制文件到/usr/rocketmq路径下
unzip rocketmq-all-4.2.0-bin-release.zip -d /usr/local/rocketmq
- 参考安装文档
- 进入解压后的bin目录
- 表示启动
nohup sh mqnamesrv &
- 查看服务名字是否启动成功
查看日志,最后一行显示这个表示启动成功
The Name Server boot success. serializeType=JSON
- 启动rocketMq程序
启动broker
nohup sh mqbroker -n 127.0.0.1:9876 &
- 可以通过查看java进程查看是否启动成功
ps -ef|grep java
- 关闭namesrv和broker执行的命令
sh mqshutdown namesrv
sh mqshutdown broker
1.3. 安装rocketMQ的可视化控制台
- 从github下载
- 进入rocketmq-console中执行mvn打包命令(编译)
mvn clean package -Dmaven.test.skip=true
- target目录中通过java -jar的方式运行。
- 出现无法连接获取broker信息
1)修改配置文件,名称路由地址为namesrvAddr,修改为公网ip+端口号
2)src/main/resource/application.properties处修改
rocketmq.config.namesrvAddr=xxx.xxx.xxx.xxx:9876
- 默认访问端口为localhost:8080这个可以修改
- 检查防火墙,安全组规则的端口是否开启。
1.4. 阿里云配置RocketMQ(已经安装好jdk8)
- 下载rocketMQ二进制文件,将该二进制文件解压到/usr/rocketmq目录下
- 修改rocketmq/conf中的broker.conf文档,添加brokerIP1=公网ip,添加namesrvAddr=公网ip:9876
- rocketmq占用大量内存,可能要修改内存大小
- 启动rocketmq的名称服务(路由服务),进入bin目录下
nohup sh mqnamesrv -n 公网ip:9876 &
- 在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的生产者
- application.properties添加配置
#消费者的组名
apache.rocketmq.consumer.pushConsumer=orderConsumer
#生产者的组名
apacha.rocketmq.producer.producerGroup=producer
#NameServer地址
apache.rocketmq.namesrvAddr=xxx.xxx.xxx.xxx:9876
- 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();一般在应用上下文,关闭的时候进行关闭,用上下文监听器。
}
}
初始化生产者:要指定生产者的组名,路由地址名
- 接口调用消息队列生产者,将消息放入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();
}
- 可能报错:
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开发消息队列的消费者
- 消费处理代码
@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大致流程
1.7. 常见问题处理
来源:CSDN
作者:¥诸葛村夫¥
链接:https://blog.csdn.net/qq_33322074/article/details/104100463