Rabbitmq基础

RabbitMQ

一、核心概念和组件

1、Broker

  • 一个RabbitMQ实例就是一个Broker

2、Virtual Host

  • 虚拟主机。相当于Mysql的Database,一个Broker上可以存在多个vhost,vhost之间可以相互隔离。每个vhost都有自己的队列、交换机、绑定和权限机制。vhost必须在连接时指定,默认的vhost是/

3、Exchange

  • 负责接收生产者发送的消息,并将消息路由到Queue。Exchange可以通过不同的类型和配置来实现不同的路由逻辑,常见的Exchange类型有:Direct、Topic、Headers、Fanout

4、Queue

  • 负责存储消息,并将消息传递给消费者。Queue可以通过不同的配置来实现不同的消息处理逻辑,例如:消息持久化、消息优先级、消息抵消等

5、Binding

  • 负责将Exchange和Queue连接起来,实现消息路由。Binging可以通过配置Exchange和Queue之间的关系,实现不同的路由逻辑

6、Message

  • 实际发送的消息内容,可以是任何可以被序列化的数据,例如:字符串、对象、文件等

7、Connection

  • 生产者/消费者与broker之间的TCP连接

8、Channel

  • 管道,一条双向数据流通道。不管是发布消息、订阅队列还是接收消息,这些动作都是通过管道完成。因为对于操作系统来说,建立和销毁TCP都是非常昂贵的开销,所以引入管道的概念,以复用一条TCP连接

二、Exchange

<一>、fanout(广播)

  • 路由规则非常简单,不需要处理RouteKey,会把所有发送到fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的所有Queue上

声明Exchange

java 复制代码
channel.exchangeDeclare("exchange_fanout", "fanout");
//将消息发送给exchange
channel.basicPublish("exchange_fanout","",null,msg.getBytes);

声明临时队列(Temporary queues)

  • 一个non_durable(不持久化的)、exclusive(单独的)、autodelete(随着消费者的消亡自动删除)、random(随机命名)的队列
java 复制代码
String queueName = channel.queueDeclare().getQueue();

绑定(Bindings)

  • 绑定queue和exchange
java 复制代码
channel.queueBind("队列名","exchange名","");

<二>、Direct

  • exchange和queue通过routeKey绑定,消息传递时,RouteKey必须完全匹配,才会被队列接收,否则该消息会被抛弃

声明Exchange

java 复制代码
channel.exchangeDeclare("exchange_direct", "direct");

发布消息

  • 发布消息时带上RouteKey
java 复制代码
channel.basicPublish("exchange_direct","routeKey_direct",null,msg.getBytes);

绑定(Bindings)

  • 绑定queue和exchange,可以带一个RouteKey参数,表示队列只对该routeKey的消息感兴趣
java 复制代码
channel.queueBind(queueName,exchangeName,RouteKey);

<三>、topic

direct类型的Exchange路由规则是完全匹配binding Key与RouteKey,但这种严格的匹配方式在很多情况下不能满足实际业务需求,topic类型的exchange在匹配规则上进行了扩展,它约定:

  • a)、routekey为一个句点号"."分隔的字符串,如"stock.usd.nyse"、"nyse.vmw"、"quick.orange.rabbit"
  • b)、binding key与routekey一样也是句点号"."分隔的字符串
  • c)、binding key可以存在两种特殊字符""与"#",用于做模糊匹配,其中'"'用于匹配一个单词,"#"用于匹配多个单词(可以是零个)

所有发送到Topic Exchange的消息被转发到所有关心RouteKey指定Topic的Queue上,声明多个RouteKey,同时声明多个Binding Key进行模糊匹配,比如"log.#"能够匹配到"log.info.oa",但是"log.",只会匹配到log.error

声明Exchange

java 复制代码
channel.exchangeDeclare("exchange_topic", "topic", false, true, null);

声明RouteKey

java 复制代码
private final static String ROUTING_KEY = "log.info";

发布消息

  • 发布消息时带上RouteKey
java 复制代码
channel.basicPublish("exchange_topic", ROUTING_KEY, null, msg.getBytes);

绑定(Bindings)

  • 绑定queue和exchange,可以带一个RouteKey参数,表示队列只对该routeKey的消息感兴趣
  • 此时消费者的RouteKey可以带上通配符
java 复制代码
private final static String ROUTING_KEY = "log.#";
java 复制代码
channel.queueBind(queueName,exchangeName,ROUTING_KEY );

<四>、headers

  • headers类型的exchange不依赖于routekey与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配
  • 在绑定queue与exchange时指定一组键值对;当消息发送到Exchange时,rabbitmq会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue

fanout和headers类型都不需要路由键routeKey,交换时通过Headers头部来将消息映射到队列的,Hash结构中要求携带一个键"x-match",这个键的Value可以是Any或者All,这代表消息携带的Hash是需要全部匹配(all),还是仅匹配一个键Any就可以了,相比直连交换机,首部交换机的优势是匹配的规则不被限定为字符串(string)而是Object类型

  • any:只要在发布消息时携带的有一对键值对headers满足队列定义的多个参数arguments的其中一个就能匹配上,注意这里是键值对的完全匹配,只匹配到键了,值却不一样是不行的
  • all:在发布消息时携带的所有Entry必须和绑定在队列上的所有Entry完全匹配

生产者:

声明Exchange

java 复制代码
channel.exchangeDeclare("exchange_topic", "headers");

声明键值对

java 复制代码
Map<String, Object> heardersMap = new HashMap<String, Object>();
heardersMap.put("api", "login");
heardersMap.put("version", 1.0);
heardersMap.put("radom", UUID.randomUUID().toString());
BasicProperties.Builder properties = new BasicProperties().builder().headers(heardersMap);

发布消息

  • 发布消息时带上键值对
java 复制代码
channel.basicPublish(EXCHANGE_NAME, "", properties.build(), msg.getBytes());

消费者:

声明键值对

java 复制代码
Map<String, Object> arguments = new HashMap<String, Object>();
arguments.put("x-match", "any");
arguments.put("api", "login");
arguments.put("version", 1.0);
arguments.put("dataType", "json");

绑定(Bindings)

  • 绑定queue和exchange,无需路由键RouteKey,但是仍然不能写成null,需要写成空字符串
java 复制代码
 channel.queueBind(queueName, EXCHANGE_NAME, "", arguments);
java 复制代码
// all:匹配失败,缺少{"dataType", "json"}
Map<String, Object> heardersMap = new HashMap<String, Object>();
heardersMap.put("api", "login");
heardersMap.put("version", 1.0);

// all:匹配成功,生产者多发送一个head没关系
Map<String, Object> heardersMap = new HashMap<String, Object>();
heardersMap.put("api", "login");
heardersMap.put("version", 1.0);
heardersMap.put("dataType", "json");
heardersMap.put("ext", false);

Map<String, Object> arguments = new HashMap<String, Object>();
arguments.put("x-match", "all");
arguments.put("api", "login");
arguments.put("version", 1.0);
arguments.put("dataType", "json");

//------------------------------------------
// any: 匹配成功,只要有一个键值对能满足队列的arguments即可
Map<String, Object> heardersMap = new HashMap<String, Object>();
heardersMap.put("api", "login");

Map<String, Object> arguments = new HashMap<String, Object>();
arguments.put("x-match", "any");
arguments.put("api", "login");
arguments.put("version", 1.0);
arguments.put("dataType", "json");

// any: 匹配失败,键值对中的key和value必须全部匹配上
Map<String, Object> heardersMap = new HashMap<String, Object>();
heardersMap.put("api", "regist");

Map<String, Object> arguments = new HashMap<String, Object>();
arguments.put("x-match", "any");
arguments.put("api", "login");
arguments.put("version", 1.0);
arguments.put("dataType", "json");

三、RabbitMQ控制台

相关推荐
SL_staff7 小时前
3天上线OKR系统:一名HR与1名工程师如何用JVS完成全栈交付
java·低代码·开源
wzdark9 小时前
基于链表的内存池设计与内存复用机制4
java·数据结构·链表
cnkeysky9 小时前
idea 中的 maven 项目重新加载子模块
java·idea
Escalating_xu9 小时前
【System V 信号量】从 P/V 原语到 Builder 封装:写出可控、可清理的进程互斥组件
java·linux·开发语言·jvm
今天AI了吗9 小时前
什么是 AI Agent?它与直接调用大模型 API 有何区别
java·网络·人工智能·架构·java-ee
隐退山林9 小时前
JavaEE进阶:SpringAOP
java·java-ee
Wang's Blog9 小时前
Java框架快速入门: Spring Security+OAuth2之方法级安全注解
java·安全·spring
JavacKaka10 小时前
LiteFlow规则引擎实战博客-2026-09-09
java
学渣超10 小时前
记一次复杂业务功能重构——从过程式长链路,到模板方法构建体系
java·架构·代码规范
Bs_MoneyMagnet10 小时前
基于springboot+vue的旅游景区点评系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·旅游