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控制台

相关推荐
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫4 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
李小白664 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp5 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶5 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb