springboot继承rocketmq
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.9.3</version>
</dependency>
修改配置文件
rocketmq:
name-server: 127.0.0.1:9876 # rocketMq的nameServer地址
producer:
group: rocketmq-springboot-group # 生产者组别
生产者
@SpringBootTest
public class RocketmqSpringbootTest {
@Resource
private RocketMQTemplate rocketMQTemplate;
@Test
void ProducerTest(){
rocketMQTemplate.syncSend("bootTestTopic","我是boot的一个消息");
}
}
消费者
@Component
@RocketMQMessageListener(topic = "bootTestTopic",consumerGroup = "boot-test-consumer-group")
public class SimpleMsgListener implements RocketMQListener<MessageExt> {
@Override
public void onMessage(MessageExt messageExt) {
System.out.println(new String(messageExt.getBody()));
}
}
重复消费问题
BROADCASTING(广播)模式下,所有注册的消费者都会消费,而这些消费者通常是集群部署的一个个微服务,这样就会多台机器重复消费,当然这个是根据需要来选择。
CLUSTERING(负载均衡)模式下,如果一个topic被多个consumerGroup消费,也会重复消费。
思路:设置唯一标识,每次消费之前判断唯一标识是否存在
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
</dependency>
消费者方使用布隆过滤器进行去重
public static BitMapBloomFilter bloomFilter = new BitMapBloomFilter(100);
@Test
public void testRepeatConsumer() throws Exception {
// 创建默认消费者组
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer-group");
consumer.setMessageModel(MessageModel.BROADCASTING);
// 设置nameServer地址
consumer.setNamesrvAddr("localhost:9876");
// 订阅一个主题来消费 表达式,默认是*
consumer.subscribe("TopicTest", "*");
// 注册一个消费监听 MessageListenerConcurrently是并发消费
// 默认是20个线程一起消费,可以参看 consumer.setConsumeThreadMax()
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
// 拿到消息的key
MessageExt messageExt = msgs.get(0);
String keys = messageExt.getKeys();
// 判断是否存在布隆过滤器中
if (bloomFilter.contains(keys)) {
// 直接返回了 不往下处理业务
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
// 这个处理业务,然后放入过滤器中
// do sth...
bloomFilter.add(keys);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.in.read();
}
消息堆积问题
1. 生产者生产的速度太快了,可以在生产方做业务限流,增加消费者数量,但是消费者数量<=队列数量,适当的设置最大的消费线程数量(根据IO(2n)/CPU(n+1))
2. 增加新的Topic进行引流,然后把所有消费者节点的目标Topic转向新的Topic,并紧急上线一组新的消费者,只负责转储,就是消费老Topic中的积压消息,并转储到新的Topic中。
如何保证消息不丢失?
- 生产者使用同步发送模式 ,收到mq的返回确认以后 顺便往自己的数据库里面写
- 消费者消费以后 修改数据这条消息的状态 = 1
- 写一个定时任务 间隔两天去查询数据 如果有status = 0 and time < day-2
- 将mq的刷盘机制设置为同步刷盘
- 使用集群模式 ,搞主备模式,将消息持久化在不同的硬件上
- 可以开启mq的trace机制,消息跟踪机制