简述
本文主要介绍Springboot项目如何集成阿里RocketMQ服务以及基本使用
消息队列作为高并发系统的核心组件之一,能够帮助业务系统解构提升开发效率和系统稳定性。
1、注册阿里云账户,购买RocketMQ服务
1、购买RocketMQ服务,创建实例配置
2、在实例中创建消息主题Topic
3、创建消息消费者组Group
注意规则:
一个 Group ID 代表一个 Consumer 实例群组。同一个消费者 Group ID 下所有的 Consumer 实例必须保证订阅的 Topic 一致,
并且也必须保证订阅 Topic 时设置的过滤规则(Tag)一致
2、配置Maven依赖
<!-- RocketMQ依赖 -->
<dependency>
<groupId>com.aliyun.openservices</groupId>
<artifactId>ons-client</artifactId>
<version>1.8.4.Final</version>
</dependency>
3、Application.yml参数配置
## 阿里RocketMQ配置
rocketmq:
## 连接点地址 参考控制台实例详情
name-server: http://MQ_INST_666666666666666666666
## 主题
topic: test_topic
## 过滤标签
tag: test_tag
producer:
## 订阅者组
group:test_group
consumer:
## 阿里云密码
access-key: xxxxxxxxxxxxxxx
secret-key: xxxxxxxxxxxxxxx
# 消费者线程
thread-num: 20
4、创建消息的生产者
消息的生产者主要为产生消息对象,他们向消息队列中发送消息。
@Configuration
public class ProducerClient {
@Value("${rocketmq.name-server}")
private String serverAddress;
@Value("${rocketmq.producer.group}")
private String group;
@Value("${rocketmq.consumer.access-key}")
private String accessKey;
@Value("${rocketmq.consumer.secret-key}")
private String secretKey;
@Bean(initMethod = "start", destroyMethod = "shutdown")
public ProducerBean buildProducer() {
ProducerBean producer = new ProducerBean();
//配置文件
Properties properties = new Properties();
// AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.setProperty(PropertyKeyConst.AccessKey, accessKey);
// SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.setProperty(PropertyKeyConst.SecretKey, secretKey);
// 设置 TCP 接入域名,进入控制台的实例管理页面的“获取接入点信息”区域查看
properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, serverAddress);
//设置发送超时时间,单位毫秒
properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000");
//设置组id
properties.setProperty(PropertyKeyConst.GROUP_ID, group);
producer.setProperties(properties);
return producer;
}
}
5、生产者消息-异步发送结果处理类
消息的异步发送为主要的消息发送方式,该方式需要进行处理发送结果。
@Slf4j
public class RocketSendAsyncMessage implements SendCallback {
@Override
public void onSuccess(SendResult sendResult) {
log.info(">>>>> 【生产者】系统时间:[{}]异步发送消息MsgID=[{}]成功!", LocalDateTime.now(),sendResult.getMessageId());
}
@Override
public void onException(OnExceptionContext onExceptionContext) {
log.info(">>>>> 【生产者】系统时间:[{}]异步发送消息MsgID=[{}]失败!", LocalDateTime.now(),onExceptionContext.getMessageId());
}
}
6、生产者消息工具类
生产者可以生成不同的消息,根据消息类型的不同,发送方式也不一样。
@Slf4j
@Component
public class RocketMQUtil {
@Autowired
ProducerBean producer;
@Value("${rocketmq.topic}")
private String topic;
@Value("${rocketmq.tag}")
private String tag;
/**
* 发送普通消息
* @param content 消息内容
* */
public void sendMessage(String content){
Message msg = new Message();
//设置主题和标签
msg.setTopic(topic);
msg.setTag(tag);
msg.setBody(content.getBytes());
try {
SendResult sendResult = producer.send(msg);
// 同步发送消息,只要不抛异常就是成功
if (sendResult != null) {
log.info(">>>>> 【生产者】系统时间:[{}]同步发送消息成功, MsgID=[{}]", LocalDateTime.now(),sendResult.getMessageId());
}
}catch (Exception e) {
// 消息发送失败
log.info(">>>>> 【生产者】系统时间:[{}]同步发送消息成功, Topic=[{}]", LocalDateTime.now(),msg.getTopic());
// 需要重试或者持久化数据进行补偿处理
e.printStackTrace();
}
}
/**
* 发送异步消息消息
* @param content 消息内容
* */
public void sendAsyncMessage(String content){
Message msg = new Message();
//设置主题和标签
msg.setTopic(topic);
msg.setTag(tag);
msg.setBody(content.getBytes());
producer.sendAsync(msg,new RocketSendAsyncMessage());
}
/**
* 发送oneWay消息消息
* @param content 消息内容
* */
public void sendOneWayMessage(String content){
Message msg = new Message();
//设置主题和标签
msg.setTopic(topic);
msg.setTag(tag);
msg.setBody(content.getBytes());
producer.sendOneway(msg);
}
}
7、消费者客户端
消费者客户端主要用来进行消息的消费操作,即处理订阅的消息队列中的消息。
@Configuration
public class ConsumerClient {
@Value("${rocketmq.name-server}")
private String serverAddress;
@Value("${rocketmq.topic}")
private String topic;
@Value("${rocketmq.tag}")
private String tag;
@Value("${rocketmq.producer.group}")
private String group;
@Value("${rocketmq.consumer.access-key}")
private String accessKey;
@Value("${rocketmq.consumer.secret-key}")
private String secretKey;
@Value("${rocketmq.consumer.thread-num}")
private String threadNum;
@Autowired
private MyRocketMessageListener messageListener;
@Bean(initMethod = "start", destroyMethod = "shutdown")
public ConsumerBean buildConsumer() {
//消费者对象bean
ConsumerBean consumerBean = new ConsumerBean();
//配置文件
Properties properties = new Properties();
//设置消费者信息
properties.setProperty(PropertyKeyConst.AccessKey, accessKey);
properties.setProperty(PropertyKeyConst.SecretKey, secretKey);
properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, serverAddress);
//设置组id
properties.setProperty(PropertyKeyConst.GROUP_ID, group);
//将消费者线程数固定为20个 20为默认值
properties.setProperty(PropertyKeyConst.ConsumeThreadNums, threadNum);
consumerBean.setProperties(properties);
//配置订阅关系
Map<Subscription, MessageListener> subscriptionTable = new HashMap<>();
//当前为订阅一个主题配置(订阅多个topic一样设置)
Subscription subscription = new Subscription();
subscription.setTopic(topic);
subscription.setExpression(tag);
subscriptionTable.put(subscription, messageListener);
consumerBean.setSubscriptionTable(subscriptionTable);
return consumerBean;
}
}
8、消费者客户端消息监听器
消费者客户端通过监听器来接收队列发送的消息,再监听器中可以添加消息的简单处理逻辑。
@Slf4j
@Component
public class MyRocketMessageListener implements MessageListener {
@Autowired
private RocketMQService rocketMQService;
@Override
public Action consume(Message message, ConsumeContext context) {
// 业务处理逻辑
log.info(">>>>> 【消费者】系统时间:[{}]接收消息MsgId=[{}],消息内容:{}",LocalDateTime.now(),message.getMsgID(),new String(message.getBody(), StandardCharsets.UTF_8));
try {
//添加消息到数据库
rocketMQService.addMessage(message);
return Action.CommitMessage;
} catch (Exception e) {
//消费失败
log.error(">>>>> 【消费者】系统时间:[{}]处理消息MsgId=[{}], 当前消费失败, 开始重试......!",LocalDateTime.now(),message.getMsgID());
return Action.ReconsumeLater;
}
}
}