使用reactor-rabbitmq库监听Rabbitmq

文章目录

Reactor RabbitMQ 简介

Reactor RabbitMQ 是 Reactor 项目的一部分,旨在提供基于 Project Reactor 的 RabbitMQ 响应式编程支持。它将 RabbitMQ 的消息队列功能与 Reactor 的非阻塞、背压友好特性结合,适用于高吞吐量的异步消息处理场景。

注意: Reactor RabbitMQ 是对原生amqp-client 的封装,同样性能强大简单易用。reactor-rabbitmq是spring-boot-starter-amqp 之外的另外一种选择。

维度 AMQP-Client Reactor RabbitMQ Spring Boot Starter AMQP
编程模型 命令式、手动管理 响应式、非阻塞 声明式、自动配置
框架依赖 无 Reactor Spring Boot
适用场景 轻量级/非 Spring 项目 响应式微服务 Spring Boot 企业应用
资源管理 手动 自动 自动
功能丰富度 基础协议操作 背压、高并发优化 事务、确认、死信队列等
学习曲线 中等(需理解 AMQP) 高(需掌握 Reactor) 低(Spring 生态友好)

Reactor RabbitMQ核心特性

  • 响应式流支持 :基于 Reactor 的 Flux 和 Mono 实现消息的发布与订阅。
  • 背压管理:自动处理消费者与生产者之间的速率匹配。
  • 非阻塞 API:避免传统 RabbitMQ 客户端的线程阻塞问题。
  • 声明式配置:支持通过代码或配置文件定义队列、交换机和绑定。

使用方法

添加依赖

在 Maven 项目中添加以下依赖:

xml 复制代码
<dependency>  
    <groupId>io.projectreactor.rabbitmq</groupId>  
    <artifactId>reactor-rabbitmq</artifactId>  
    <version>1.5.6</version>  
</dependency>  
创建连接
java 复制代码
ConnectionFactory connectionFactory = new ConnectionFactory();  
connectionFactory.setHost("localhost");  
Sender sender = RabbitFlux.createSender(  
    Mono.fromCallable(() -> connectionFactory.newConnection())  
);  
Receiver receiver = RabbitFlux.createReceiver(  
    Mono.fromCallable(() -> connectionFactory.newConnection())  
);  
发送消息
java 复制代码
sender.send(  
    Flux.just(new OutboundMessage(  
        "exchange-name",  
        "routing-key",  
        "Hello RabbitMQ".getBytes()  
    ))  
).subscribe();  
接收消息
java 复制代码
receiver.consumeAutoAck("queue-name")  
    .map(delivery -> new String(delivery.getBody()))  
    .subscribe(System.out::println);  

高级配置

消息确认模式

支持自动确认(autoAck)和手动确认(manualAck):

java 复制代码
receiver.consumeManualAck("queue-name")  
    .delayUntil(delivery ->  
        delivery.ack()  
            .thenReturn(delivery.getBody())  
    )  
    .subscribe();  
错误处理

通过 Reactor 的 onError 机制处理异常:

java 复制代码
sender.send(messages)  
    .doOnError(e -> System.err.println("Send failed: " + e))  
    .retry(3)  
    .subscribe();  

集群监听(自动ACK)
java 复制代码
 // 1. 配置集群连接
        ReceiverOptions receiverOptions = new ReceiverOptions()
                .connectionFactory(new ConnectionFactory() {{
                    setUsername("guest");
                    setPassword("guest");
                }})
                .connectionSupplier(cf -> cf.newConnection(
                        new Address[]{
                                new Address("localhost", 5672),
                                new Address("localhost", 5673),
                                new Address("localhost", 5674)
                        },
                        "reactive-cluster"
                ));

        // 2. 创建 Receiver
        Receiver receiver = RabbitFlux.createReceiver(receiverOptions);


        // 监听队列(自动负载均衡)
        receiver.consumeAutoAck("queue1") // 队列名(需在集群中预先创建)
                .subscribe(
                        delivery -> {
                            String message = new String(delivery.getBody());
                            System.out.println("收到消息: " + message);
                        },
                        error -> System.err.println("监听错误: " + error)
                );
 // 保持程序运行
        Mono.never().block();
集群监听手动ACK
java 复制代码
// 1. 配置集群连接
        ReceiverOptions receiverOptions = new ReceiverOptions()
                .connectionFactory(new ConnectionFactory() {{
                    setUsername("guest");
                    setPassword("guest");
                }})
                .connectionSupplier(cf -> cf.newConnection(
                        new Address[]{
                                new Address("localhost", 5672),
                                new Address("localhost", 5673),
                                new Address("localhost", 5674)
                        },
                        "reactive-cluster"
                ));

        // 2. 创建 Receiver
        Receiver receiver = RabbitFlux.createReceiver(receiverOptions);

        // 消费消息并手动ACK
        receiver.consumeManualAck("queue1")
                .flatMap(delivery -> {
                    try {
                        String message = new String(delivery.getBody());
                        log.info("received message:" + message);
                        // 业务逻辑处理...
                        boolean success = false;
                        int i = RandomUtil.randomInt();
                        if (i % 2 == 0) {
                            success = true;
                        }

                        if (success) {
                            log.info("ack success");
                            // 处理成功,手动ACK
                            return Mono.fromRunnable(() -> delivery.ack())
                                    .thenReturn("ACK");
                        } else {
                            log.info("ack fail");
                            // 处理失败,手动NACK(可选择重试或丢弃)
                            return Mono.fromRunnable(() -> delivery.nack(true)) // false表示不重新入队
                                    .thenReturn("NACK");
                        }
                    } catch (Exception e) {
                        // 异常情况,NACK并可选择重试
                        delivery.nack(true); // true表示重新入队
                        return Mono.error(e);
                    }
                })
                .subscribe(
                        result -> log.info("Message processed:" + result),
                        error -> log.info("Error:" + error)
                );

        // 保持程序运行
        Mono.never().block();

性能优化建议

  • 连接复用 :避免频繁创建/关闭连接,使用 Mono 缓存连接。
  • 批量发送 :通过 Flux.buffer() 合并多条消息后一次性发送。
  • 线程池调优 :自定义 Scheduler 以匹配业务场景的并发需求。

适用场景

  • 微服务间的异步通信。
  • 事件驱动的数据处理流水线。
  • 需要高吞吐量和低延迟的消息系统。

如需进一步功能(如事务、RPC 模式),可参考官方文档或源码示例。

相关推荐
宸津-代码粉碎机3 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
程序猿乐锅4 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
ly76894 小时前
RabbitMQ 消费确认与预取:manual ack、reject、nack 与 QoS 的取舍
rabbitmq·死信队列·消息可靠性·消费确认·qos 预取
灯澜忆梦5 小时前
【RabbitMQ #7】 | 消息转换器
分布式·rabbitmq·ruby
需要8266 小时前
分布式事务:Seata AT/TCC/SAGA 的取舍与踩坑
java·spring boot·分布式·spring·spring cloud
CS创新实验室9 小时前
为什么三台机器就能选出一个“带头大哥“?——Raft 一致性算法,一次讲透
分布式·操作系统
本人手速666+10 小时前
企微开发API如何设计客户冻结状态?WeComApi 在删除、投诉和异常客户场景中的自动化边界
运维·分布式·自动化·企业微信·企微外部群开发·wecomapi·企业微信二次开发
灯澜忆梦12 小时前
【RabbitMQ #4】 | Work 任务模型
分布式·rabbitmq
程序猿乐锅12 小时前
【黑马点评 | 第七篇】Redis 分布式锁的两种实现
java·数据库·redis·分布式·spring·缓存
千里码aicood13 小时前
基于Hadoop的机票价格波动分析系统的设计与实现
大数据·hadoop·分布式