RabbitMQ: 消息发送、连接管理、消息封装与三种工程方案

RabbitMQ组件封装 1.组件需求 需求:需要单独设计一个模块用来封装rabbitmq 其他应用之间引用,做简单少量的配置,即可发送消息,消息的发送要保证可靠的投递 2.组件架构选型 消息组件:rabbitMQ 消息可靠性保证:使用elasticjob查询数据库相关表记录来对消息进行可靠投递 3.模块分类 相关依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" 阅读详情

RabbitTemplate 的核心作用与设计思想


RabbitTemplate 是 AMQP 通信的高级抽象层,其设计借鉴了模板方法模式(Template Method Pattern)。核心功能包括:

  1. 连接管理:自动处理 Connection 和 Channel 的创建/复用
  2. 消息序列化:内置 JSON/二进制等转换逻辑
  3. 异常恢复:提供重试机制与连接容错
  4. 资源优化:防止 Channel 泄漏,确保资源释放

关键设计原则:通过 execute 方法封装底层操作,开发者只需关注业务逻辑的 Lambda 表达式。

NestJS 集成 RabbitMQ 的完整流程


1 ) 初始化 RabbitTemplate

// rabbit.module.ts
import { Module } from '@nestjs/common';
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import * as amqp from 'amqp-connection-manager';
 
@Module({
  imports: [
    RabbitMQModule.forRootAsync(RabbitMQModule, {
      useFactory: () => ({
        exchanges: [{ name: 'order_exchange', type: 'direct' }],
        uri: 'amqp://localhost:5672',
        connectionInitOptions: { wait: true },
        connectionManager: amqp.connect(['amqp://localhost']),
      }),
    }),
  ],
  exports: [RabbitMQModule],
})
export class RabbitModule {}

2 ) 消息发送的两种模式
方案A:原始字节流发送(精确控制消息属性)

// order.service.ts
import { RabbitRPC } from '@golevelup/nestjs-rabbitmq';
import { Injectable } from '@nestjs/common';
import * as amqp from 'amqplib';
 
@Injectable()
export class OrderService {
  constructor(private readonly amqpService: RabbitMQModule) {}
 
  async createOrder() {
    const message = JSON.stringify({ orderId: Date.now() });
    const buffer = Buffer.from(message);
    
    // 设置消息属性(如TTL)
    const options: amqp.Options.Publish = {
      expiration: '15000', // 15秒TTL
      headers: { 'x-retry-count': 3 },
    };
 
    await this.amqpService.publish(
      'order_exchange',
      'order.restaurant.key',
      buffer,
      options
    );
  }
}

方案B:对象自动序列化(简化发送)

// 同一Service内替代方案
async createOrderSimple() {
  const order = { orderId: Date.now(), items: ['item1', 'item2'] };
  
  // 自动序列化为JSON
  await this.amqpService.publish(
    'order_exchange',
    'order.restaurant.key',
    order // 直接传入对象
  );
}

工程示例:NestJS 的 RabbitMQ 全链路实现


1 ) 方案1:基础消息发送(自动连接管理)

// 生产者:src/producers/order.producer.ts
@Injectable()
export class OrderProducer {
  constructor(
    @InjectRabbitMQ() private readonly rabbitClient: RabbitMQ.Client
  ) {}
 
  async sendOrderEvent(order: OrderDto) {
    await this.rabbitClient.publish(
      'order_exchange',
      'order.created',
      Buffer.from(JSON.stringify(order))
    );
  }
}
 
// 消费者:src/consumers/order.consumer.ts
@Controller()
export class OrderConsumer {
  @RabbitSubscribe({
    exchange: 'order_exchange',
    routingKey: 'order.created',
    queue: 'restaurant_queue',
  })
  handleOrderEvent(message: any) {
    console.log('Received order:', message);
  }
}

2 ) 方案2:带确认机制的事务消息

// 配置发布确认
await this.rabbitClient.publish(
  'order_exchange',
  'order.payment',
  message,
  {
    persistent: true, // 持久化
    mandatory: true, // 确保路由成功 
  }
);
 
// 监听Broker确认
this.rabbitClient.on('return', (msg) => {
  console.error('Message returned:', msg.fields.routingKey);
});

3 ) 方案3:RPC 模式请求响应

// 服务端
@RabbitRPC({
  exchange: 'rpc_exchange',
  routingKey: 'get_order',
  queue: 'order_rpc_queue',
})
async getOrderRpcHandler(orderId: string) {
  return this.orderService.findById(orderId);
}
 
// 客户端调用
const response = await this.rabbitClient.request<Order>({
  exchange: 'rpc_exchange',
  routingKey: 'get_order',
  payload: orderId,
  timeout: 5000, // 5秒超时
});

关键问题解决方案


1 ) 连接异常处理

// 重连配置(rabbit.module.ts)
connectionManager: amqp.connect(['amqp://localhost'], {
  reconnectTimeInSeconds: 5, // 5秒重试间隔 
  heartbeatIntervalInSeconds: 60,
}),

2 ) 消息属性缺失问题
必须显式设置消息头(原始方案需构建完整属性):

const options: amqp.Options.Publish = {
  headers: { 'x-version': '1.0' },
  contentType: 'application/json',
};

3 ) 底层原理验证
RabbitTemplate 最终调用 channel.basicPublish(),可通过调试跟踪:

// 查看源码调用栈
this.rabbitClient.publish → ChannelWrapper.publish → amqplib.Channel.publish

RabbitMQ 管理命令参考


# 创建交换器
rabbitmqadmin declare exchange name=order_exchange type=direct
 
# 绑定队列
rabbitmqadmin declare queue name=restaurant_queue durable=true
rabbitmqadmin declare binding source=order_exchange destination=restaurant_queue routing_key=order.restaurant.key
 
# 监控消息
rabbitmqctl list_queues name messages_ready

三种工程方案对比


方案适用场景优势注意事项
基础发送简单事件通知实现简单,低延迟无确认机制
事务消息支付/订单等关键业务数据可靠性高,支持重试性能损耗约10-20%
RPC 模式服务间实时数据查询同步获取响应,逻辑直观需处理超时和熔断

技术要点总结


  1. 连接工厂必要性:
    RabbitTemplate 必须注入 Connection 实例,否则抛出 NPE(Null Pointer Exception)

  2. 消息封装差异:

    • send() 需手动构建 Buffer 和消息属性
    • publish() 支持对象自动序列化(默认JSON)
  3. 生产级实践:

    // 消息持久化配置
    @RabbitSubscribe({
      queueOptions: { durable: true },
      enableControllerDiscovery: true,
    })
    
  4. 性能优化建议:

    • 使用 ChannelPool 复用 Channel(默认缓存25个)
    • 批量发送启用 publishBatch()
    • 高并发场景关闭 Confirm 模式

设计启示:模板方法模式通过 execute 封装:

    1. 连接诊断 → 2. 信道分配 → 3. 异常重试 → 4. 资源回收

补充知识点


1 ) 死信队列配置

// 创建死信交换器
await this.rabbitClient.assertExchange('dlx_exchange', 'direct');
 
// 绑定原始队列
await this.rabbitClient.assertQueue('restaurant_queue', {
  deadLetterExchange: 'dlx_exchange',
  deadLetterRoutingKey: 'failed_orders',
});

2 ) 消息压缩策略

import * as zlib from 'zlib';
 
async sendCompressedMessage(payload: any) {
  const compressed = zlib.gzipSync(JSON.stringify(payload));
  await this.rabbitClient.publish(
    'orders', 
    'order.created', 
    compressed,
    { contentType: 'application/gzip' }
  );
}

3 ) 分布式追踪集成

// 添加OpenTelemetry头信息
const tracingHeaders = {
  'traceparent': currentSpan.context().toString(),
};
 
await this.rabbitClient.publish(
  'orders',
  'order.created',
  payload,
  { headers: tracingHeaders }
);

本文完整实现了从基础连接到高阶实践的 RabbitMQ 集成方案,保留原始业务逻辑的同时,通过三种工程方案展示 NestJS 下的消息通信最佳实践。

RabbitMQ 客户端 连接、发送、接收处理消息 (3) 如果 RabbitMQ 服务收到消息,就转发给 注册接收消息接口的 连接,如果接收的连接标记了 AutoDelete,那么发送给客户端后,RabbitMQ 就会将消息从消息队列中删除。而 RabbitMQ 的消费消息(接收消息) 也仅仅是接收消息,它不管是谁发的消息,只要是发送的 RabbitMQ 服务的消息,它都能接收,注册接收消息,我的客户端就会收到 RabbitMQ 发送过来的消息,消息中包含发送上来的消息内容,还有发送消息的 queue 名字。 阅读详情

相关推荐

rabbitmq管理页面发送消息

Delivery mode: 是否持久化,1 - Non-persistent,2 - Persistent Headers:Headers can have any name. Only long string headers can be set here. __TypeId__: 消息体实体类类型 当需要在消费端对应实体类接受时 需要设置该属性 值为对应实体类在项目下的全路径 ${包名....

tank_panda的博客 6028

消息队列——RabbitMq

一、消息队列的使用场景 一、消息队列的使用场景) 一、消息队列的使用场景 异步处理 应用解耦 流量削锋 消息通讯 【1】异步处理:场景说明:用户注册后,需要发注册邮件和注册短信。 引入消息队列后架构如下:用户的响应时间=注册信息写入数据库的时间,例如50毫秒。发注册邮箱、发注册短信写入消息队列后,直接返回客户端,因写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。 按照传统的做法: ①、串行方式,将注册信息写入数据库成功后,发注册邮件,再发送注册短信,以上三个成功后,返回客户端。可

weixin_45080272的博客 6565

精通RabbitMQ:C#中的消息发送与接收

高级消息队列协议(AMQP)是一种网络协议,它允许符合标准的应用程序进行消息传递。AMQP的客户端可以发送消息给服务器,服务器可以将消息交给消费者。AMQP定义了消息系统中的消息模型、消息队列、交换器、绑定等核心组件。

weixin_30336531的博客 954

RabbitMQ消息发送和接收(实例)

的消息只能被同一个消费者消费,如果没有消费监听队列那么消息会存放到队列中持久化保存,直到有消费者来消费这个消息,如果有消费者监听队列则立即消费发送到队列中的消息。4.模拟连续向队列中放两次消息,这两条消息的队列名称相同,内容不同。再次返回消息队列,此时消息队列已经没有了消息,消息已经模拟出队了。7.此时进入控制台查看队列,发现队列中的消息已经全部取出。修改Idea消息的内容再向队列里发送一次消息。修改Idea消息的内容再向队列里发送一次消息。模拟从队列中取出消息,查看取出的消息内容。

weixin_59334478的博客 1万+

RabbitMQ工具类封装实现

封装了RabbitMQ的订阅者线程和发布者线程(还有个初始化工厂的连接工具类),另外附加一个安卓的使用demo

node-amqp-connection-manager:自动重新连接和循环支持amqplib

amqplib的连接管理。 amqp连接管理器 这是围绕的包装程序,它提供了自动重新连接。 特征 当您的经纪人在火灾中死亡时,将自动重新连接。 集群中多个代理之间的循环连接。 如果在代理不可用时发送消息,则将消息在内存中排队,直到我们重新连接为止。 同时支持promise和回调(使用 ) 非常简单的库-围绕的薄包装。 安装 npm install --save amqplib amqp-connection-manager 基本 这里的基本思想是,通常,当您创建一个新频道时,您会在开始时进行一些设置工作(例如断言存在各种队列或交换,或绑定到队列),然后发送和接收消息,而您从不再次触摸这些东西。 每当当前连接的代理死亡时,amqp-connection-manager将重新连接到新的代理。 当您向amqp-connection-manager询问一个通道时,您指定一个或多个要运行的

基于RabbitMQ的异步消息传递:发送与消费

mq消息队列

uncle_ll的博客 2595

AI 模型训练核心方法论:零基础也能落地的 8 个关键阶段

本文是为 AI 零基础学习者打造的模型训练入门指南,以生活化语言拆解核心概念,规避专业术语壁垒。内容先通俗阐释模型训练、监督学习、数据集划分等基础概念,再按问题定义、数据准备、模型选择、环境搭建、训练、评估、调参、部署 8 个阶段,拆解完整训练流程,搭配 PyTorch 代码示例与实战案例,同时提供资源预算、常见问题解决方案及学习路径。指南强调数据的核心重要性,推荐新手优先使用迁移学习和免费 GPU 资源,兼顾理论与实操,帮助学习者快速上手,避开训练误区,独立完成从模型搭建到部署的全流程。

weixin_52741870的博客 469

SpringBoot整合RabbitMQ并实现消息发送与接收

消息队列(Message Queue)是一种高效的异步通信机制,它在分布式应用系统中扮演着重要的角色。简单来说,消息队列将消息发送者和消息接收者解耦,消息发送者只需要将消息发送给队列,而不需要知道消息是如何被消费者处理的,同时,消息接收者也只需要从队列中订阅自己需要的消息,而不需要知道这些消息是由哪个发送者发送的。消息队列能够提高应用程序的可扩展性、可靠性以及灵活性,并且能够缓解高并发情况下的压力。 RabbitMQ 是一个开源的 AMQP 消息代理软件,它基于 Erlang/OTP 平台

心态的博客 3798

向NCBI上传16S rDNA数据的操作详解

专门介绍向NCBI上传16S rDNA数据的方法不太多。因为自己有上传数据的需要,所以决定边摸索边写下操作流程。如果这篇博文交代了上传步骤以及一些描述文件属性的书写,帮到你的话,还请点赞收藏。

yue81560的博客 2万+

初识数据结构之入门必懂——线性表(顺序表)

本文将介绍数据结构中的线性表与线性表中最简单的结构——顺序表

m0_64705485的博客 905

简单Rabbitmq 发送消息和接收消息

简单Rabbitmq 发送消息和接收消息 1 先在Rabbitmq配置文件中预先创建好交换器,队列,路由等信息。 2 创建生产者发送消息 @Autowired private RabbitTemplate rabbitTemplate; private void mqSendMessage(UserOperLog userOperLog) throws Exception{ rabbitTemplate.setExchange("test.file.ex.

DK微风的博客 7562

用ESP32-S3+OV2640摄像头+ILI9488屏,DIY一个能联网的智能猫眼(附完整代码)

本文详细介绍了如何利用ESP32-S3微控制器搭配OV2640摄像头和ILI9488显示屏,DIY一个功能强大的智能猫眼系统。从硬件选型、电路设计到软件开发,提供了完整的解决方案和优化技巧,包括图像采集显示、WiFi远程访问及低功耗设计,适合智能家居爱好者动手实践。

weixin_30897233的博客 503
上一篇: RabbitMQ: 声明式配置简化管理
下一篇: RabbitMQ: 高级特性实践之生产者确认与消费者容器实现
Wang's Blog
博客等级 码龄12年 7438粉丝 2422原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值