RabbitMQ学习(3)- RabbitMQ结构

目录

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用来设置是否在交换器没有被使用的情况下删除

 

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_36191137/article/details/85176313