Rabbit 实例

一、概述

在mq消息队列中主要分广播式消息、持久式消息、死信式消息。

**广播式(Fanout,如 hos_notice_task):**不看路由键、无脑复制,一条消息发给所有绑定的队列各一份------"公告群发,人人有份"(通知前端专用,发时路由键传空串)

**持久式/业务式(Topic/Direct,如 hos_topic → 各业务队列):**按"路由键=队列名"精确匹配投递,消息持久化躺在队列里等消费,一条消息只被处理一次------"一件活只干一遍,消息落地为安"

**死信(TTL + DLX 延时,如 hos_delay_exchange):**消息在源队列睡到 TTL 到期变死信,再按死信路由键转投实发队列、到点消费一次------"设个闹钟,到点才响"

一句话记忆:广播=群发复制,业务=点对点持久,死信=到点触发------三种模式对应三种诉求:"人人都要知道"、"一件活干一次"、"到时候再看结果"。

二、广播式

实例化示例如下:

java 复制代码
 public static final String NOTICE_FANOUT_NAME = "hos_notice_task";
 
 @Bean
 public FanoutExchange noticeFanoutExchange() {
     return new FanoutExchange(NOTICE_FANOUT_NAME, false, false);
 }

三、持久式/业务式

实例化示例如下:

java 复制代码
  public static final String TOPICS_NAME = "hos_topic";

  @Bean
  public TopicExchange hosTopicExchange() {
     return new TopicExchange(TOPICS_NAME, true, false);
  }

四、死信

实例化示例如下:

java 复制代码
public static final String DELAY_EXCHANGE = "hos_delay_exchange";

@Bean(DELAY_EXCHANGE)
public Exchange delayExchange() {
    return ExchangeBuilder.topicExchange(DELAY_EXCHANGE).durable(true).build();
}

五、队列(Queue)

实例化示例如下:

java 复制代码
public static final String TEST_SAVE_QUEUE_NAME = "hos_test_save";
    
@Bean
public Queue testSaveQueue() {
    return new Queue(TEST_SAVE_QUEUE_NAME, true);
}

队列(queue)的四种初始化函数

java 复制代码
new Queue(String name)
new Queue(String name, boolean durable)
new Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
new Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

| 参数 | 含义 | 用法 |
|---|---|---|
| `name` | 队列名,全局唯一 | `hos_test`、`hos_test_save`... |
| `durable` | 队列定义**持久化**:broker 重启队列还在 | 全部 `true` |
| `exclusive` | 排他:只归声明它的连接用,连接断开即删 | 全部 `false`(业务队列要共享) |
| `autoDelete` | 最后一个消费者退出后自动删队列 | 全部 `false`(断连不删,消息要留存) |
| `arguments` | 扩展参数 Map:延时 / 死信 / 优先级都在这 | 优先级队列、死信源队列使用 |

注意:durable=true 只保**队列定义**,不保**消息**。消息要持久必须发布时标 deliveryMode=2;new Queue(name, true) 等价于 durable=true、exclusive=false、autoDelete=false。

六、绑定(Binding)

注意:绑定与队列成对出现,一个绑定对应一个队列

实例化示例如下:

java 复制代码
@Bean
public Binding bindingTestSaveQueue() {
   return BindingBuilder.bind(testSaveQueue()).to(hosTopicExchange()).with(TEST_SAVE_QUEUE_NAME);
}


new Binding(destination, destinationType, exchange, routingKey, arguments)

BindingBuilder.bind(队列).to(交换机).with(绑定键).noargs()

| 要素 | 含义 | 用法 |
|---|---|---|
| `destination` | 消息去哪 | `bind(队列)` |
| `destinationType` | 目标是队列还是交换机(支持交换机→交换机) | `QUEUE`(默认) |
| `exchange` | 消息从哪个交换机来 | `.to(hosTopicExchange())` / `.to(delayExchange())` |
| `key` | 绑定键:消息路由键与它相等/通配才投递 | 恒等于队列名(项目约定) |
| `arguments` | 绑定参数(headers 交换机的 `x-match` 等) | 无(`.noargs()`) |

七、arguments

实例化示例如下:

java 复制代码
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-max-priority", 10);
arguments.put("x-dead-letter-exchange", DELAY_EXCHANGE);
arguments.put("x-dead-letter-routing-key", ACT_FIVE_MINUTE_NOTICE_QUEUE);
arguments.put("x-message-ttl", 60000 * 5);
return new Queue(TEST_QUEUE_NAME, true, false, false, arguments);

|---------------------------|------------------------------|
| 参数 | 含义 |
| x-message-ttl | 消息存活时间(**毫秒**),到期变死信/被丢弃 |
| x-dead-letter-exchange | 死信交换机:过期/被拒/超长后转投给谁 |
| x-dead-letter-routing-key | 死信路由键:转投时消息用什么键匹配 |
| x-max-priority | 优先级上限,值越大越先被消 |

八、发送端

发送消息统一用RabbitTemplate 的 convertAndSend 方法

实例化示例如下:

java 复制代码
//普通 JSON 消息(ProcessAutoSender)
rabbitTemplate.convertAndSend(
        RabbitConfig.TOPICS_NAME,                    // 交换机 hos_topic
        RabbitConfig.PREPROCESS_AUTO_QUEUE_NAME,     // 路由键 = 队列名
        jsonStr);                                    // 消息体:JSON 字符串

//带优先级(testSender,队列声明 x-max-priority=10)
rabbitTemplate.convertAndSend(
        RabbitConfig.TOPICS_NAME,
        RabbitConfig.TEST_QUEUE_NAME,
        jsonStr,
        msg -> {
            msg.getMessageProperties().setPriority(priority);
            return msg;
        });

//Fanout 广播(NoticeSender)------路由键必须传空串
rabbitTemplate.convertAndSend(RabbitConfig.NOTICE_FANOUT_NAME, "", JsonUtils.toJsonStr(notice));

九、接收端

接收:@RabbitListener + @RabbitHandler

@RabbitListener(queues=xxxx) 声明监听哪个队列

@RabbitHandler 标记处理方法

实例化示例如下:

java 复制代码
// 按 Map 解析
@RabbitListener(queues = RabbitConfig.TEST_SAVE_QUEUE_NAME)
@RabbitHandler
public void testSave(String message, Channel channel) {
    Map msg = JsonUtils.parseObject(message, Map.class);
    String test= (String) msg.get("test");
    ...
}

// 按 DTO 解析
@RabbitListener(queues = RabbitConfig.TEST_RESULT_QUEUE_NAME)
@RabbitHandler
public void cephResult(String message, Channel channel) {
    DTO resultDTO = JsonUtils.parseObject(message, DTO.class);
    Long taskId = resultDTO.getTaskId();
    ...
}

// Fanout 接收用匿名队列绑定(websocket NoticeConsumer):
@RabbitListener(bindings = @QueueBinding(
        value = @Queue,                                          // 匿名队列,自动生成
        exchange = @Exchange(value = RabbitConfig.NOTICE_FANOUT_NAME,
                             durable = "false", type = ExchangeTypes.FANOUT)))  // 没有 key
@RabbitHandler
public void noticeResult(String message, Channel channel) throws Exception {
    Map<String, String> notice = new HashMap<>();
    notice.put("type", "notice");
    notice.put("content", message);
    webSocketSessionManager.broadcast(JsonUtils.toJsonStr(notice)); 
}

十、结语

消息体统一 JSON 字符串,收发双方字段对齐,跨模块联调基本零歧义。如果你也在做微服务拆解、任务异步化,这套"交换机-队列-绑定-死信"的落地姿势可以直接抄作业。有任何细节欢迎评论区交流。

相关推荐
weixin_448771721 小时前
使用Aspose给PDF添加水印
java·pdf
\光辉岁月/1 小时前
7.system类
java·system类
综合简报1 小时前
黑五海外发稿投给谁?三类海外媒体发稿渠道的分工
开发语言·php·媒体
SL_staff1 小时前
BI落地失败的3个技术断点:从数据接入、自助分析到服务闭环的工程实践
java·数据分析·数据可视化
大风起兮云飞扬丶1 小时前
Java——线程池
java·开发语言
我命由我123452 小时前
Python 开发 - Python 虚拟环境
运维·开发语言·后端·python·http·https·java-ee
c#上位机2 小时前
C#上位机项目实战——exe项目调试更改dll中源代码
开发语言·c#
basketball6162 小时前
C++ 中字符串与常见类型的转换总结
开发语言·c++
梦影_2 小时前
MySQL进阶教程(一)—— 储存过程与触发器(上)
开发语言·数据库·后端·sql·mysql·中间件