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(推荐使用) 在业务代码中实现事务. 可知编程式事务每 ...
随机推荐
- HDU 1029Ignatius and the Princess IV
Ignatius and the Princess IV Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32767 K ( ...
- 蛋疼的 403 Forbidden You don’t have permission to access / on this server.
参考博文: a.http://www.linuxidc.com/Linux/2016-09/134827.htm 这个解释挺好 昨天配置新服务器:以为自己老手 就一步到位结果一直出现 403 For ...
- dotNET面试(二)
值类型与引用类型 1.值类型和引用类型的区别? 值类型包括简单类型.结构体类型和枚举类型,引用类型包括自定义类.数组.接口.委托等. 赋值方式:将一个值类型变量赋给另一个值类型变量时,将复制包含的值. ...
- c++简单线程池实现(转)
线程池,简单来说就是有一堆已经创建好的线程(最大数目一定),初始时他们都处于空闲状态,当有新的任务进来,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中,供其他 ...
- Bootstrap 小功能
<div class="container"> <div class="navbar-header"> <button type= ...
- 如何用Word制作斜线表头?
如何用Word制作斜线表头?遇到这种问题,你一般是如何操作?本期企业网盘坚果云干货分享与大家分享有关斜线表头的制作方法. 斜线表头分单斜线表头和多斜线表头,下面分情况来了解相关的解决办法. 单斜线表头 ...
- 【leetcode】921. Minimum Add to Make Parentheses Valid
题目如下: 解题思路:上周都在忙着参加CTF,没时间做题,今天来更新一下博客吧.括号问题在leetcode中出现了很多,本题的解题思路和以前的括号问题一样,使用栈.遍历Input,如果是'('直接入栈 ...
- Vue学习笔记【33】——相关文章
vue.js 1.x 文档 vue.js 2.x 文档 String.prototype.padStart(maxLength, fillString) js 里面的键盘事件对应的键码 Vue.js双 ...
- PHP disk_total_space() 函数
定义和用法 disk_total_space() 函数返回指定目录的磁盘总容量,以字节为单位. 语法 disk_total_space(directory) 参数 描述 directory 必需.规定 ...
- python 标准模块和第三方模块
>>> help('modules') Please wait a moment while I gather a list of all available modules... ...