springboot整合RocketMq(非事务)
1、配置文件
1、yml配置文件
rocketmq: #mq配置
producer:
iseffect: true
type: default # (transaction,default) transaction:TransactionMQProducer; default:DefaultMQProducer
groupName: testzjlGroup
topicName: test_topic
namesrvAddr: 192.168.244.128:9876
consumer:
iseffect: true
type: default # (transaction,default) transaction:TransactionMQProducer; default:DefaultMQProducer
groupName: testzjlGroup
topicName: test_topic
namesrvAddr: 192.168.244.128:98762、对应的java类
package com.gofun.customer.mq; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "rocketmq.producer")
public class RocketMqProducerProperties { private Boolean iseffect;
private String type;
private String groupName;
private String topicName;
private String namesrvAddr; public Boolean getIseffect() {
return iseffect;
} public void setIseffect(Boolean iseffect) {
this.iseffect = iseffect;
} public String getType() {
return type;
} public void setType(String type) {
this.type = type;
} public String getGroupName() {
return groupName;
} public void setGroupName(String groupName) {
this.groupName = groupName;
} public String getTopicName() {
return topicName;
} public void setTopicName(String topicName) {
this.topicName = topicName;
} public String getNamesrvAddr() {
return namesrvAddr;
} public void setNamesrvAddr(String namesrvAddr) {
this.namesrvAddr = namesrvAddr;
}
}
2、DefaultMQProducer生产者
1、生产者配置
package com.gofun.customer.mq; import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
@EnableConfigurationProperties(RocketMqProducerProperties.class)
@ConditionalOnProperty(prefix = "rocketmq.producer", name = "iseffect", havingValue = "true")
public class RocketMqConfig {
@Autowired
private RocketMqProducerProperties rocketMqProperties; @Bean
@ConditionalOnProperty(prefix = "rocketmq.producer", name = "type", havingValue = "default")
public DefaultMQProducer defaultMQProducer() throws MQClientException {
DefaultMQProducer defaultMQProducer = new DefaultMQProducer(rocketMqProperties.getGroupName());
defaultMQProducer.setNamesrvAddr(rocketMqProperties.getNamesrvAddr());
defaultMQProducer.setVipChannelEnabled(false);
defaultMQProducer.setRetryTimesWhenSendAsyncFailed(10);
defaultMQProducer.start();
return defaultMQProducer;
} }
- 启动应用创建生产者
- 使用配置文件为RocketMqProducerProperties类
- 配置文件iseffect = true时生效该配置
- 配置文件 type=default 时生效 DefaultMQProducer 生产者
2、生产者工具类
package com.gofun.customer.mq; import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; @Component
public class RocketMqProducer {
@Autowired
private DefaultMQProducer defaultMQProducer;
@Autowired
private RocketMqProducerProperties rocketMqProperties; public SendResult send(String topic, String tag, Object obj) {
String body = null;
if(obj == null){
return null;
}
if(obj instanceof String){
body = (String) obj;
}else{
body = JSON.toJSONString(obj);
}
Message msg = new Message(topic, tag, body.getBytes());
SendResult sendResult = null;
try {
sendResult = defaultMQProducer.send(msg);
} catch (Exception e) {
}
return sendResult;
} /**
* 延时消息
* @param topic
* @param tag
* @param obj
* @param delayTimeLevel 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
* @return
*/
public SendResult send(String topic, String tag, Object obj,int delayTimeLevel) {
String body = null;
if(obj == null){
return null;
}
if(obj instanceof String){
body = (String) obj;
}else{
body = JSON.toJSONString(obj);
}
Message msg = new Message(topic, tag, body.getBytes());
msg.setDelayTimeLevel(delayTimeLevel);
SendResult sendResult = null;
try {
sendResult = defaultMQProducer.send(msg);
} catch (Exception e) {
}
return sendResult;
} public SendResult send(String tag, Object obj) {
return send(rocketMqProperties.getTopicName(), tag, obj);
} }3、生产者发送消息
1、引入工具类调用 发送方法
@Autowired
private RocketMqProducer rocketMqProducer;
rocketMqProducer.send("testTag","测试mq发送消息。。。。");4、问题
注意:
- mq设置autoCreateTopicEnable=false时需要手动创建topic
- 启动后后台一直报打印日志如:closeChannel: close the connection to remote address[] result: true 说明namesrvAddr 的ip 或 端口号配置错误
- 启动后后台一直报打印日志如:closeChannel: close the connection to remote address[192.168.244.128:9876] result: true 可能是jar包错误
- 要引入fastjson的jar包
3、消费者
1、DefaultMQPullConsumer 消费者
private static final Map<MessageQueue,Long> OFFSE_TABLE = new HashMap<MessageQueue,Long>(); public void testDefaultMQPullConsumer() throws MQClientException {
DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(rocketMqConsumerProperties.getGroupName());
consumer.setNamesrvAddr("192.168.244.128:9876;192.168.244.130:9876");
consumer.start();
// 从指定topic中拉取所有消息队列
Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("order-topic");
for(MessageQueue mq:mqs){
try {
// 获取消息的offset,指定从store中获取
long offset = consumer.fetchConsumeOffset(mq,true);
System.out.println("consumer from the queue:"+mq+":"+offset);
while(true){
PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
putMessageQueueOffset(mq,pullResult.getNextBeginOffset());
switch(pullResult.getPullStatus()){
case FOUND:
List<MessageExt> messageExtList = pullResult.getMsgFoundList();
for (MessageExt m : messageExtList) {
System.out.println(new String(m.getBody()));
}
break;
case NO_MATCHED_MSG:
break;
case NO_NEW_MSG:
break;
case OFFSET_ILLEGAL:
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
consumer.shutdown();
} // 保存上次消费的消息下标
private static void putMessageQueueOffset(MessageQueue mq, long nextBeginOffset) {
OFFSE_TABLE.put(mq, nextBeginOffset);
} // 获取上次消费的消息的下标
private static Long getMessageQueueOffset(MessageQueue mq) {
Long offset = OFFSE_TABLE.get(mq);
if(offset != null){
return offset;
}
return 0l;
}2、DefaultMQPushConsumer 消费者模板方法
RocketMqConsumerProperties 配置类 参见 消费者配置类。
package com.gofun.customer.mq; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired; import java.util.List; public abstract class RocketMqDefaultConsumer {
@Autowired
private RocketMqConsumerProperties rocketMqConsumerProperties; public void listener(String topic, String tag) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(rocketMqConsumerProperties.getGroupName());
consumer.setNamesrvAddr(rocketMqConsumerProperties.getNamesrvAddr());
consumer.subscribe(topic, tag);
// 开启内部类实现监听
// consumer.registerMessageListener((MessageListenerConcurrently) (list, consumeConcurrentlyContext) -> RocketMqDefaultConsumer.this.dealBody(list));
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
return RocketMqDefaultConsumer.this.dealBody(list);
}
});
consumer.start();
} // 处理body的业务
public abstract ConsumeConcurrentlyStatus dealBody(List<MessageExt> msgs);
}
- 消费者需要继承此抽象类
- 传入topic 和 tag,添加监听, 开启消费者
- 定义抽象函数处理消息,实现类需要自已实现处理函数内容
3、DefaultMQPushConsumer 消费者实现
package com.gofun.customer.controller.test; import com.gofun.customer.mq.RocketMqDefaultConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import java.util.List; @Component
public class TestConsumer extends RocketMqDefaultConsumer implements InitializingBean {
private final String testtopic = "test_topic";
private final String testflag = "testTag"; @Override
public void afterPropertiesSet() throws Exception {
super.listener(testtopic, testflag);
} @Override
public ConsumeConcurrentlyStatus dealBody(List<MessageExt> msgs) {
if (!CollectionUtils.isEmpty(msgs)) {
for (MessageExt msg : msgs) {
byte[] body = msg.getBody();
String s = new String(body);
System.out.println("这是rocketmq消费者消费的消息:"+s);
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} }
- 继承模板类定义自己的topic和tag
- 实现处理消息的方法
- 实现接口InitializingBean ,加载完成自动调用 afterPropertiesSet方法,父类模板添加监听
3、消费模式
在RocketMQ中,可以理解为没有ActiveMQ的createQueue()和createTopic()的用法,也就是并没有P2P和Pub/Sub类似的概念。RocketMQ不遵循JMS规范,而是使用了一套自定义的机制。可以理解为RocketMQ都是基于Pub/Sub发布订阅模式的,
在此基础上提供了集群消息和广播消息两种消息模式,可通过消费端方法consumer.setMessageModel()进行设置。
集群消息——MessageModel.CLUSTERING
这方方式可以实现类似ActiveMQ负载均衡客户端的功能,同一个ConsumerGroup下的所有Consumer已负载均衡的方式消费消息。比较特殊的是,这种方式可以支持生产端先发送消息到Broker,消费端再订阅主题进行消费,比较灵活。RocketMQ默认为该模式。
广播消息——MessageModel.BROADCASTING
在这种模式下,生产端发送到Topic下的消息,会被订阅了该Topic的所有Consumer消费,即使它们处于同一个ConsumerGroup。
原文链接:https://blog.csdn.net/weixin_34452850/article/details/82754419
3、顺序消息
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer id = (Integer) arg;
int index = id % mqs.size();
return mqs.get(index);
}
}, orderId);
参考:https://www.jianshu.com/p/5260a2739d80
springboot整合RocketMq(非事务)的更多相关文章
- SpringBoot(17)---SpringBoot整合RocketMQ
SpringBoot整合RocketMQ 上篇博客讲解了服务器集群部署RocketMQ 博客地址:RocketMQ(2)---Docker部署RocketMQ集群 这篇在上篇搭建好的基础上,将Spri ...
- Springboot整合RocketMQ解决分布式事务
直接上代码: 代码结构如下: 依次贴出相关类: DataSource1Config: package com.example.demo.config;import org.apache.ibatis. ...
- MongoDB与SpringBoot整合(支持事务)
1.创建SpringBoot工程,选择 Web.MonogDB 依赖,pom如下: <parent> <groupId>org.springframework.boot< ...
- SpringBoot整合RocketMQ
1.RocketMQ的下载与配置 到官网选择想要的版本下载即可,https://rocketmq.apache.org/release_notes/ 下载速度会比较慢,这里提供目前最新版本4.9.3的 ...
- SpringBoot - 集成RocketMQ实现延迟消息队列
目录 前言 环境 具体实现 前言 RocketMQ是阿里巴巴在2012年开源的分布式消息中间件,记录下SpringBoot整合RocketMQ的方式,RocketMQ的安装可以查看:Windows下安 ...
- 【SpringBoot】数据库操作之整合Mybaties和事务讲解
========================8.数据库操作之整合Mybaties和事务讲解 ================================ 1.SpringBoot2.x持久化数 ...
- SpringBoot整合Mybatis【非注解版】
接上文:SpringBoot整合Mybatis[注解版] 一.项目创建 新建一个工程 选择Spring Initializr,配置JDK版本 输入项目名 选择构建web项目所需的state ...
- SpringBoot系列七:SpringBoot 整合 MyBatis(配置 druid 数据源、配置 MyBatis、事务控制、druid 监控)
1.概念:SpringBoot 整合 MyBatis 2.背景 SpringBoot 得到最终效果是一个简化到极致的 WEB 开发,但是只要牵扯到 WEB 开发,就绝对不可能缺少数据层操作,所有的开发 ...
- @Transactional(事务讲解)和springboot 整合事务
概述 事务在编程中分为两种:声明式事务处理和编程式事务处理 编程式事务处理:编码方式实现事务管理,常与模版类TransactionTemplate(推荐使用) 在业务代码中实现事务. 可知编程式事务每 ...
随机推荐
- springCloud的使用02-----服务消费者(rest+ribbon)
1 将服务提供者做成集群模式 配置service-hi的端口为8762进行启动,配置service-hi的端口为8763进行启动, service-hi会在ecureka server上注册两个ser ...
- java虚拟机规范(se8)——class文件格式(二)
4.4 常量池 java虚拟机指令并不依赖类.接口.类实例或者数组的运行时布局.相反,指令依靠常量池中的符号信息. 所有的常量池条目都有如下的通用结构: cp_info { u1 tag; u1 in ...
- python打包生成exe文件
今天任务让做一个可以在Win上直接执行的脚本,百度了下原来可以生产.exe文件.神奇了 安装 pyInstaller pip install pyInstaller 进入要打包文件的目录 执行 py ...
- js与html中unicode编码的使用
js中 // unicode在字符串中使用格式:\u四位编码,一定是四位,否则报错 // 显示 @ 符 console.log(`十六进制 unicode 编码 0x0040 对应的字符是:${'\u ...
- java 多线程实现的四种方式
一个线程的生命周期 线程是一个动态执行的过程,它也有一个从产生到死亡的过程. 下图显示了一个线程完整的生命周期. 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程 ...
- 2019-9-29-dotnet-对-DateTime-排序
title author date CreateTime categories dotnet 对 DateTime 排序 lindexi 2019-09-29 14:55:49 +0800 2019- ...
- windows下如何使用Git上传代码
首先,在使用Git的同时,我们需要拥有码云账号,在官网注册即可(官网:https://gitee.com/). 注册结束后创建一个代码仓库,最好和要上传的文件夹名字一样: 1.首先在电脑上安装wind ...
- 2019牛客暑期多校训练营(第九场)A.The power of Fibonacci
题意:给出n和m,f(n)是斐波那契额数列的第n项,要求计算ans=f(1)^m+f(2)^m+....f(n)^m.即斐波那契额数列前n项的m次幂和. 解法:这题好像有两种解法:一种是循环节+CRT ...
- win10 + VS2015 编译 ARPACK
step 1: 下载ARPACK , mingw-w64-install 和 mingw-get-inst-20120426.exe: step 2: 安装 MinGW-64默认安装路径即可. ste ...
- MySQL慢SQL语句常见诱因
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11429037.html 1. 无索引.索引失效导致慢查询 如果在一张几千万数据的表中以一个没有索引的列 ...