RocketMQ随笔

第1章 RocketMQ 5.x核心变化

https://gitee.com/little_lunatic/message-middleware

1.1 版本升级亮点

  • 轻量级Proxy模式:解耦Broker与客户端协议(支持gRPC/Remoting双协议)
  • 全新客户端APIrocketmq-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 )

事务消息监听:@RocketMQTransactionListenerRocketMQLocalTransactionListener


附录:依赖配置

<!-- 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>

关键注意事项

  1. 协议选择:gRPC协议(默认8081端口)性能更优,Remoting协议(8082端口)兼容旧版
  2. 线程模型:新客户端采用异步IO模型,避免阻塞业务线程
  3. 消息轨迹:需额外部署OpenTelemetry Collector进行数据收集
  4. Proxy扩容:多个Proxy实例可共用同一Broker集群

MQ何如让消息不丢失?

哪些环节会丢失消息

  • 生产者发消息(跨网)

  • 消费者消费消息(跨网)

  • Broker主从同步(跨网)

  • Broker将消息保存到磁盘(MQ先将消息存入操作系统的缓存,由操作系统异步将消息存入磁盘,如果服务挂了,缓存中还未写入磁盘的消息就会丢失)

跨网导致的消息丢失:生产者确认机制;

borker保存丢失:可以使用同步刷盘

MQ如何保证消息顺序消费?

保证消息局部有序,生产者将消息发送到同一个消息队列,消费者从同一个消费队列取消息

MQ如何保证消息幂等性?

1.生产者发送消息如何保持幂等

发送消息时,RocketMQ给每条消息分配了唯一ID

2.消费者消费消息如何保持幂等

业务代码控制,可以对已处理的消息加唯一ID历史缓存。对于批量消息,需要自定义唯一id存放到key中。

MQ如何快速处理积压的消息?

1、快速扩容消费者

增加消费者实例、增加消费线程数

2、优化消费逻辑

耗时的同步转异步处理、批量消费与批量处理

3、消息迁移与临时队列

临时队列分流:创建临时 Topic 和 Consumer,快速消费积压消息。

消息迁移工具:使用 MQ 自带工具或开发自定义迁移工具。

其他:监控与预警、流量削峰填谷、业务降级。

posted @ 2025-05-25 20:12  little_lunatic  阅读(82)  评论(0)    收藏  举报