RocketMQ随笔
第1章 RocketMQ 5.x核心变化
https://gitee.com/little_lunatic/message-middleware
1.1 版本升级亮点
- 轻量级Proxy模式:解耦Broker与客户端协议(支持gRPC/Remoting双协议)
- 全新客户端API:
rocketmq-client-java重构,包名改为org.apache.rocketmq.client - 增强消息轨迹:内置OpenTelemetry支持
- POP消费模式:Pull-Oriented Consumption(替代部分Push模式场景)
- 事务消息2.0:优化事务检查机制
第2章 环境部署
2.1 使用Proxy模式部署(推荐)
# 下载RocketMQ 5.1.4
wget https://archive.apache.org/dist/rocketmq/5.1.4/rocketmq-all-5.1.4-bin-release.zip
# 启动NameServer
nohup ./bin/mqnamesrv &
# 启动Broker(启用自动创建Topic)
nohup ./bin/mqbroker -n localhost:9876 --enable-proxy &
# 启动Proxy(独立进程)
nohup ./bin/mqproxy -n localhost:9876 &
第3章 生产者API(新客户端)
3.1 同步发送消息
public class Producer5Demo {
public static void main(String[] args) throws Exception {
ClientServiceProvider provider = ClientServiceProvider.loadService();
ProducerBuilder builder = provider.newProducerBuilder()
.setTopics("TestTopic")
.setClientConfiguration(
new ClientConfiguration()
.setEndpoints("localhost:8081") // Proxy端口
);
try (Producer producer = builder.build()) {
Message message = provider.newMessageBuilder()
.setTopic("TestTopic")
.setTag("TagA")
.setBody("Hello RocketMQ 5".getBytes())
.build();
SendReceipt receipt = producer.send(message);
System.out.println("Send success! MessageId: " + receipt.getMessageId());
}
}
}
3.2 事务消息2.0
TransactionChecker checker = messageView -> {
// 检查本地事务状态
return TransactionResolution.COMMIT;
};
try (Producer producer = provider.newProducerBuilder()
.setTransactionChecker(checker)
// ...其他配置
.build()) {
TransactionMessageBuilder txMsgBuilder = provider.newTransactionMessageBuilder();
Message message = txMsgBuilder.setTopic("TxTopic")
.setBody("Transaction Msg".getBytes())
.build();
producer.send(message, null); // 自动触发事务检查
}
第4章 消费者API(新客户端)
消费者处理消息的两种模式:广播模式 MessageModel.BROADCASTING、集群模式MessageModel.CLUSTERING
4.1 SimpleConsumer(POP模式)
public class SimpleConsumer5Demo {
public static void main(String[] args) throws Exception {
ClientServiceProvider provider = ClientServiceProvider.loadService();
ClientConfiguration config = new ClientConfiguration()
.setEndpoints("localhost:8081");
FilterExpression filter = new FilterExpression("TagA", FilterExpressionType.TAG);
SimpleConsumer consumer = provider.newSimpleConsumerBuilder()
.setConsumerGroup("MyGroup")
.setClientConfiguration(config)
.setAwaitDuration(Duration.ofSeconds(10))
.setSubscriptionExpressions(Collections.singletonMap("TestTopic", filter))
.build();
while (true) {
List<MessageView> messages = consumer.receive(10, Duration.ofSeconds(30));
for (MessageView message : messages) {
System.out.println("Received: " + message);
try {
consumer.ack(message);
} catch (ClientException e) {
e.printStackTrace();
}
}
}
}
}
4.2 PushConsumer(兼容模式)
PushConsumerBuilder pushConsumerBuilder = provider.newPushConsumerBuilder()
.setConsumerGroup("PushGroup")
.setClientConfiguration(config)
.setMessageListener(messageView -> {
System.out.println("Push received: " + messageView);
return ConsumeResult.SUCCESS;
});
try (PushConsumer pushConsumer = pushConsumerBuilder.build()) {
pushConsumer.subscribe("TestTopic", filter);
Thread.sleep(Long.MAX_VALUE);
}
第5章 消息类型增强
5.1 定时消息(精准时间)
// 设置消息在2023-10-01 00:00:00投递
long timestamp = LocalDateTime.of(2023, 10, 1, 0, 0)
.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
Message message = provider.newMessageBuilder()
.setTopic("TimerTopic")
.setDeliveryTimestamp(timestamp)
.setBody("Delayed message".getBytes())
.build();
5.2 顺序消息
// 生产者指定ShardingKey
Message message = provider.newMessageBuilder()
.setTopic("OrderTopic")
.setBody("Order-001".getBytes())
.setShardingKey("Order-001") // 相同Key进入同一队列
.build();
// 消费者需实现顺序处理逻辑(自行保证线程安全)
第6章 高级特性
6.1 消息轨迹追踪
// 启用OpenTelemetry(需添加依赖)
TracingConfiguration tracingConfig = new TracingConfiguration(
OpenTelemetryTracer.builder()
.setServiceName("my-service")
.build()
);
Producer producer = provider.newProducerBuilder()
.setTracingConfiguration(tracingConfig)
// ...其他配置
.build();
6.2 客户端指标监控
# 配置Prometheus(客户端)
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.16.0</version>
</dependency>
ClientConfiguration config = new ClientConfiguration()
.setMetricCollector(new PrometheusCollector());
第7章 最佳实践
7.1 Proxy模式调优
# proxy.conf
proxy.grpc.server.port=8081
proxy.remoting.server.port=8082
proxy.topic.route.cache.enable=true
7.2 消息过滤(SQL92语法)
FilterExpression expression = new FilterExpression(
"age BETWEEN 18 AND 30 AND region = 'China'",
FilterExpressionType.SQL
);
还可以通过Tag过滤消息。
7.3 客户端容错策略
ClientConfiguration config = new ClientConfiguration()
.setEndpoints("proxy1:8081,proxy2:8081")
.setRetryPolicy(new ExponentialBackoffRetryPolicy()
.setMaxAttempts(5)
.setInitialDelay(Duration.ofMillis(100))
.setLoadBalancer(new WeightedRandomLoadBalancer());
Spring Boot 整合 RocketMQ
<!--spring boot 整个rocketmq-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.3.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- RocketMQ Client -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>5.3.0</version>
</dependency>
发送消息:RocketMQTemplate
接收消息实现:RocketMQListener 及注解
@RocketMQMessageListener( consumerGroup = "demo_consumer_group", topic = "tx-demo-topic", consumeMode = ConsumeMode.CONCURRENTLY )
事务消息监听:@RocketMQTransactionListener和RocketMQLocalTransactionListener
附录:依赖配置
<!-- RocketMQ 5.x客户端依赖 -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client-java</artifactId>
<version>5.1.4</version>
</dependency>
<!-- OpenTelemetry支持 -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-opentelemetry</artifactId>
<version>5.1.4</version>
</dependency>
关键注意事项
- 协议选择:gRPC协议(默认8081端口)性能更优,Remoting协议(8082端口)兼容旧版
- 线程模型:新客户端采用异步IO模型,避免阻塞业务线程
- 消息轨迹:需额外部署OpenTelemetry Collector进行数据收集
- Proxy扩容:多个Proxy实例可共用同一Broker集群
MQ何如让消息不丢失?
哪些环节会丢失消息
-
生产者发消息(跨网)
-
消费者消费消息(跨网)
-
Broker主从同步(跨网)
-
Broker将消息保存到磁盘(MQ先将消息存入操作系统的缓存,由操作系统异步将消息存入磁盘,如果服务挂了,缓存中还未写入磁盘的消息就会丢失)
跨网导致的消息丢失:生产者确认机制;
borker保存丢失:可以使用同步刷盘
MQ如何保证消息顺序消费?
保证消息局部有序,生产者将消息发送到同一个消息队列,消费者从同一个消费队列取消息
MQ如何保证消息幂等性?
1.生产者发送消息如何保持幂等
发送消息时,RocketMQ给每条消息分配了唯一ID
2.消费者消费消息如何保持幂等
业务代码控制,可以对已处理的消息加唯一ID历史缓存。对于批量消息,需要自定义唯一id存放到key中。
MQ如何快速处理积压的消息?
1、快速扩容消费者
增加消费者实例、增加消费线程数
2、优化消费逻辑
耗时的同步转异步处理、批量消费与批量处理
3、消息迁移与临时队列
临时队列分流:创建临时 Topic 和 Consumer,快速消费积压消息。
消息迁移工具:使用 MQ 自带工具或开发自定义迁移工具。
其他:监控与预警、流量削峰填谷、业务降级。


浙公网安备 33010602011771号