RabbitMQ学习(3)- RabbitMQ结构

本文详细介绍了RabbitMQ的消息中间件服务,涵盖其核心组件、交换器类型、运行流程及生产者与消费者的运行机制。深入探讨了交换器、队列的配置与管理,以及RabbitMQ如何实现消息的高效路由。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

RabbitMQ几大组件

交换器类型

RabbitMQ运行流程

Connection与Channel

生产者运行流程

消费者运行流程

细说交换器

(一)交换器

(二)队列

(三)交换器与队列

(四)交换器与交换器



RabbitMQ几大组件

  • 生产者:消息创建者,将消息发送到消息中间件的。
  • 消息:包括有效载荷与标签。有效载荷:要传输的数据;标签:描述有效载荷的属性;RabbitMQ通过标签决定谁获得该消息,消费者只能得到有效载荷。
  • 消费者:是接收消息的。
  • Brocker:是消息中间件服务的节点。一个Brocker=一个RabbitMQ,一个服务器上如果有多个RabbitMQ就有多个Brocker。
  • 队列:是用来存储消息的。
  • 交换器:交换器仅仅对消息进行转发。交换器有不同的类型(如:fanout、direct、topic、headers)
  • 路由键:交换器与队列的关系是通过绑定键(BindingKey,称为路由键)建立的。
  • 绑定 

交换器类型

RabbitMQ常用的交换器类型有fanout、direct、topic、headers四种:

  • fanout:它会把所有发送到该交换器的消息,路由到所有与该交换器绑定的队列中;
    public static void main(String[] args) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();  
    factory.setUsername("rabbitstudy");
    factory.setPassword("123456");
    factory.setHost("192.168.0.1");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
    		
    channel.queueDeclare(QUEUE_NAME1, false, false, false, null);
    channel.queueDeclare(QUEUE_NAME2, false, false, false, null);
    		
    channel.queueBind(QUEUE_NAME1, EXCHANGE_NAME, "com.cdsn.test1"); 
    channel.queueBind(QUEUE_NAME2, EXCHANGE_NAME, "com.cdsn.test2"); 
    
    		
    channel.basicPublish(EXCHANGE_NAME, "com.cdsn.test", 
    				MessageProperties.PERSISTENT_TEXT_PLAIN, 
    				"Hello World!".getBytes());
    channel.close();
    connection.close();
    }
  • direct:把消息路由到那些BindingKey和RoutingKey完全匹配的队列中;
  • topic:类似于direct,但可以使用通配符匹配规则;("#"可匹配多个或零个单词,“*”可匹配单个单词)
    public static void main(String[] args) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();  
    factory.setUsername("rabbitstudy");
    factory.setPassword("123456");
    factory.setHost("192.168.0.1");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    channel.exchangeDeclare(EXCHANGE_NAME, "topic");
    		
    channel.queueDeclare(QUEUE_NAME1, false, false, false, null);
    channel.queueDeclare(QUEUE_NAME2, false, false, false, null);
    		
    channel.queueBind(QUEUE_NAME1, EXCHANGE_NAME, "*.test"); 
    channel.queueBind(QUEUE_NAME2, EXCHANGE_NAME, "#.test"); 
    
    		
    channel.basicPublish(EXCHANGE_NAME, "com.cdsn.test", 
    				MessageProperties.PERSISTENT_TEXT_PLAIN, 
    				"Hello World!".getBytes());
    
    channel.close();
    connection.close();
    }
  • header:消息不根据路由键的匹配规则路由,而是根据发送的消息内容中的headers属性进行匹配。

RabbitMQ运行流程

  • 生产者发送消息
  1. 生产者与Broker建立连接(Connection),开启信道(Channel)

  2. 生产者声明交换器(交换器类型、是否持久化、是否自动删除等)

  3. 生产者声明队列(是否持久化、是否排他、是否自动删除)

  4. 生产者通过路由键将交换器和队列绑定

  5. 生产者发送消息至Broker(携带路由键等)

  6. 交换器根据接收到的路由键,以及交换器类型查找匹配的队列

  7. 找到,将消息存入相对应的队列中;找不到,则根据生产者的配置,选择丢弃还是退回给生产者

  8. 关闭信道、关闭连接

  • 消费者接收消息
  1. 消费者与Broker建立连接(Connection),开启信道(Channel)
  2. 消费者向Broker请求消费相应队列的消息,可能设置回调函数
  3. 等待Broker回应并投递相应队列中的消息,接收消息
  4. 消费者确认(ack)接收到的消息
  5. RabbitMQ从队列中删除相应已经被确认的消息
  6. 关闭信道、关闭连接

Connection与Channel

RabbitMQ所有的AMQP指令都是通过信道完成的。

RabbitMQ的Channel与Netty中的NIO模型区别在于Channel是建立在TCP连接之上的。


生产者运行流程

  1. 当生产者与Broker建立连接时,调用factory.newConnection()方法。
  2. 当客户端调用channel.createChannel()方法时,准备开启通道。
  3. 发送消息时,调用channel.basicPublish()方法。              

 


消费者运行流程

  1. 当客户端调用channel.basicConsume()方法时,向Broker告知准备好消费消息。
  2. 客户端调用channel.basicAck()方法,向Broker发送确认通知。

细说交换器

(一)交换器

 

         参数                                       作用
exchange交换器名称
type交换器的类型,常见如fanout、direct、topic、headers
durable设置是否持久化
autoDelete设置是否自动删除
internal

设置是否是内置的

argument其他结构化参数

备注:

持久化:交换器的创建持久化到磁盘;

自动删除:自动删除的前提是至少有一个队列或者交换器与这个交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑;

channel.exchangeDeclare(EXCHANGE_NAME, "direct", false, true, false, null);// 创建一个自动删除的交换器

内置交换器:客户端程序无法直接发送消息到交换器,只能通过交换器路由到内置交换器。


(1)不等待服务器通知创建队列成功命令:

    void channel.exchangeDeclareNoWait(String exchange,String type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) throws IOException;

(2)检测交换器是否存在,如果不存在则抛出异常:

    Exchange.DeclareOK exchangeDeclarePassive(String name) throws IOException;// 如果要用到这方法,需要解决这个异常

(3)删除交换器:

    ①  Exchange.DeleteOK exchangeDelete(String exchange) throws IOException;

    ②  void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException;

    ③  Exchange.DeleteOK exchangeDelete(String exchange, boolean ifUnused) throws IOException;

备注:

        exchange标识交换器的名称

        ifUnused用来设置是否在交换器没有被使用的情况下删除

(二)队列

声明队列:

(1)queueDeclare();

(2)queueDeclare(String queue,String exchange,String type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments);

备注:排他队列,如果一个队列被声明,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。这种队列适用于一个客户端同时发送和读取消息的应用场景。

        1、排他队列是基于连接(Connection)可见的,同一个连接的不同信道(Channel)是可以同时访问同一连接创建的排他队列;

        2、“首次”是指如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同;

        3、即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除。

声明队列参数说明:
参数作用
x-message-ttl定义消息过期时间,单位ms。
x-expires

定义队列过期时间,单位ms;

当队列在指定时间内未被使用,自动删除该队列。

x-max-length

定义队列最大长度,队列中消息最大个数;

默认消息长度是不限制的;

x-max-length-bytes限定队列最大占用的空间大小,单位B。
x-dead-letter-exchange当队列消息长度大于最大长度、或者过期等等,将从队列中删除的消息推送到指定的交换机中。
x-dead-letter-routing-key设置将删除的消息推送到指定交换机的路由键,不设置则使用原来的路由键。
x-max-priority

优先级队列。

x-queue-mode先将消息保存到磁盘上,不放在内存中,当消费者开始消费的时候才加载到内存中。

(1)不等待服务器通知创建队列成功:

void queueDeclareNoWait(String queue,boolean durable,boolean exclusive,boolean autoDelete,Map<String,Object> arguments) throws IOException; 

(2)检测队列是否存在,如果不存在则抛出异常:

Exchange.DeclareOk queueDeclarePassive(String queue) throws IOException; 

(3)删除队列:

  1. Queue.De1eteOk queueDelete(String queue) throws IOException;
  2.  Queue.De1eteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException;
  3.  void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) throws IOException;

(4)清空队列:

       Queue.PurgeOK queuePurge(String queue) throws IOException;

(三)交换器与队列

交换器与队列绑定

(1)Queue.BindOK queueBind(String queue, String exchange, String routingKey) throws IOExceptino;

(2)Queue.BindOK queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

(3)void queueBindNoWait(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

解除绑定:

(1)Queue.UnbindOK queueUnbind(String queue, String exchange, String routingKey) throws IOException;

(2)Queue.UnbindOK queueUnbind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

参数作用
queue队列的名称
exchange交换器名称
routingKey用来绑定队列和交换器的路由键
argument定义绑定的一些参数

(四)交换器与交换器

交换器与交换器绑定:

(1)Exchange.BindOK exchangeBind(String destination, String source, String routingKey) throws IOExceptino;

(2)Exchange.BindOK exchangeBind(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOExceptino;

(3)void exchangeBind(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOExceptino;

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值