一文搞定!RabbitMQ基础与Spring Boot集成

1. RabbitMQ简介

RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据。RabbitMQ是使用Erlang语言来编写的,并且基于AMQP(Advanced Message Queuing Protocol,高级消息队列协议)协议实现。

1.1 RabbitMQ的核心概念

  1. Virtual Host(虚拟主机)
    • 用于逻辑隔离,最上层的消息路由
    • 一个Virtual Host里面可以有若干个Exchange和Queue
    • 同一个Virtual Host里面不能有相同名称的Exchange或Queue
  2. Exchange(交换机)
    • 接收消息,根据路由键转发消息到绑定的队列
    • 四种类型:direct、topic、fanout、headers
    • 每种类型对应不同的路由策略
  3. Queue(队列)
    • 存储消息的实体
    • FIFO原则
    • 可以设置持久化、自动删除等属性
  4. Binding(绑定)
    • Exchange和Queue之间的虚拟连接
    • 包含routing key(路由键)
    • 决定消息如何从Exchange路由到Queue
  5. Channel(信道)
    • 建立在Connection连接内的虚拟连接
    • 复用TCP连接,减少性能开销
    • 会话的最小单位

1.2 Exchange类型详解

Exchange是RabbitMQ中最核心的组件之一,负责接收消息并将其路由到一个或多个队列。RabbitMQ提供了四种不同类型的Exchange,每种类型有不同的路由算法,适用于不同的业务场景。

1.2.1 Direct Exchange(直接交换机)

工作原理:Direct Exchange将消息路由到binding key与routing key完全匹配的队列中。

使用场景:适用于明确定向的消息传递,如特定服务的任务分发、精确的指令下发等。

常用性:高,是最常用的Exchange类型之一。

示例

@Bean
public DirectExchange userExchange() {
   
    
    
    return new DirectExchange("user.exchange");
}

@Bean
public Queue userCreateQueue() {
   
    
    
    return new Queue("user.create.queue");
}

@Bean
public Queue userUpdateQueue() {
   
    
    
    return new Queue("user.update.queue");
}

@Bean
public Binding bindUserCreate() {
   
    
    
    return BindingBuilder.bind(userCreateQueue())
            .to(userExchange())
            .with("user.create");  // routing key
}

@Bean
public Binding bindUserUpdate() {
   
    
    
    return BindingBuilder.bind(userUpdateQueue())
            .to(userExchange())
            .with("user.update");  // routing key
}

消息路由示例

  • 发送routing key为user.create的消息,只有user.create.queue队列会收到
  • 发送routing key为user.update的消息,只有user.update.queue队列会收到
  • 发送routing key为user.delete的消息,由于没有对应的binding,消息会被丢弃
1.2.2 Topic Exchange(主题交换机)

工作原理:Topic Exchange根据通配符匹配规则将消息路由到binding key与routing key模式匹配的队列中。

  • * 表示匹配一个单词
  • # 表示匹配零个或多个单词

使用场景:适用于消息的分类订阅,如日志系统的多级别过滤、多条件组合的消息订阅等。

常用性:高,在需要灵活匹配的业务场景中广泛使用。

示例

@Bean
public TopicExchange logExchange() {
   
    
    
    return new TopicExchange("log.exchange");
}

@Bean
public Queue errorQueue() {
   
    
    
    return new Queue("error.log.queue");
}

@Bean
public Queue allOrdersQueue() {
   
    
    
    return new Queue("all.orders.queue");
}

@Bean
public Queue createEventsQueue() {
   
    
    
    return new Queue("create.events.queue");
}

@Bean
public Binding bindErrorLogs() {
   
    
    
    return BindingBuilder.bind(errorQueue())
            .to(logExchange())
            .with("log.error.#");  // 匹配所有error日志
}

@Bean
public Binding bindAllOrders() {
   
    
    
    return BindingBuilder.bind(allOrdersQueue())
            .to(logExchange())
            .with("order.#");  // 匹配所有订单消息
}

@Bean
public Binding bindCreateEvents() {
   
    
    
    return BindingBuilder.bind(createEventsQueue())
            .to(logExchange())
            .with("*.*.create");  // 匹配所有create事件
}

消息路由示例

  • 发送routing key为log.error.database的消息,error.log.queue队列会收到
  • 发送routing key为order.created的消息,all.orders.queue队列会收到
  • 发送routing key为user.profile.create的消息,create.events.queue队列会收到
  • 发送routing key为order.shipping.create的消息,两个队列都会收到:all.orders.queuecreate.events.queue
1.2.3 Fanout Exchange(扇形交换机)

工作原理:Fanout Exchange将消息广播到所有绑定的队列,忽略routing key。

使用场景:适用于广播消息,如系统公告、群发通知、实时数据更新等需要一对多传递的场景。

常用性:中等,在广播场景中使用频率较高。

示例

@Bean
public FanoutExchange notificationExchange() {
   
    
    
    return new FanoutExchange("notification.exchange");
}

@Bean
public Queue emailQueue() {
   
    
    
    return new Queue("email.queue");
}

@Bean
public Queue smsQueue() {
   
    
    
    return new Queue("sms.queue");
}

@Bean
public Queue pushQueue() {
   
    
    
    return new Queue("push.queue");
}

@Bean
public Binding bindEmail() {
   
    
    
    return BindingBuilder.bind(emailQueue())
            .to(notificationExchange());
}

@Bean
public Binding bindSms() {
   
    
    
    return BindingBuilder.bind(smsQueue())
            .to(notificationExchange());
}

@Bean
public Binding bindPush() {