RabbitMQ从零开始学(四)通信模型之发布订阅模型—channel.exchangeDeclare()—channel.queueBind()

发布订阅模型(Publish/Subscribe)

简单的说就是队列里面的消息会被多个消费者同时接受到,消费者接收到的信息一致

发布订阅模型适合于做模块之间的异步通信

RabbitMQ从零开始学(四)通信模型之发布订阅模型—channel.exchangeDeclare()—channel.queueBind()_第1张图片

场景:

  1. 可以使用这种模型,发送并记录日志信息 ------ 就会被log收集程序收集到,可直接写到指定的文件里面
  2. springcloud的config组件里面通知配置自动更新
  3. 缓存同步也可以使用这一个
  4. 高并发下实现下单逻辑

编写生产者

// 生产者
public class Producer {
     
    // 声明交换机的名字
    private static final String EXCHANGE_NAME = "exchange_publish_1";
    public static void main(String[] args) throws IOException, TimeoutException {
     
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        // 声明交换机
        /**
         *  param1:exchange,交换机的名称
         *  param2:type,交换机的类型,发布订阅模式只能是 fanout
         */
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        // 发送消息到交换机
        for (int i = 0; i < 100; i++) {
     
            channel.basicPublish(EXCHANGE_NAME, "", null, ("发布订阅模型的第 " + i + " 条消息").getBytes());
        }
        // 关闭资源
        channel.close();
        connection.close();
    }
}

编写消费者

// 消费者1
public class Consumer {
     
    // 声明队列的名字
    private static final String QUEUE_NAME = "queue_publish_1";
    // 声明交换机的名字
    private static final String EXCHANGE_NAME = "exchange_publish_1";

    public static void main(String[] args) throws IOException, TimeoutException {
     
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        // 声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        // 声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        // 将队列绑定到交换机
        /**
         *  param1:destination,目的地,队列的名字
         *  param2:source,资源,交换机的名字
         *  param3:routingKey,路由键(目前没有用到routingKey,填 "" 即可)
         */
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
        // 声明消费者
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
     
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
     
                System.out.println("队列1接收到的消息是:" + new String(body));
            }
        };
        // 绑定消费者,自动应答
        channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
    }
}

编写消费者2

// 消费者2
public class Consumer2 {
     
    // 声明队列的名字
    private static final String QUEUE_NAME = "queue_publish_2";
    // 声明交换机的名字
    private static final String EXCHANGE_NAME = "exchange_publish_1";

    public static void main(String[] args) throws IOException, TimeoutException {
     
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        // 声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        // 声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        // 将队列绑定到交换机
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
        // 声明消费者
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
     
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
     
                System.out.println("队列2接收到的消息是:" + new String(body));
            }
        };
        // 绑定消费者,自动应答
        channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
    }
}

测试

先启动2个消费者,再启动生产者

运行结果

RabbitMQ从零开始学(四)通信模型之发布订阅模型—channel.exchangeDeclare()—channel.queueBind()_第2张图片
RabbitMQ从零开始学(四)通信模型之发布订阅模型—channel.exchangeDeclare()—channel.queueBind()_第3张图片
RabbitMQ从零开始学(四)通信模型之发布订阅模型—channel.exchangeDeclare()—channel.queueBind()_第4张图片
RabbitMQ从零开始学(四)通信模型之发布订阅模型—channel.exchangeDeclare()—channel.queueBind()_第5张图片

可以看出来消费者1和消费者2接收到的消息是一模一样的

channel.exchangeDeclare()

/**
 * @param exchange the name of the exchange
 * @param type the exchange type
 * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart)
 * @param autoDelete true if the server should delete the exchange when it is no longer in use
 * @param internal true if the exchange is internal, i.e. can't be directly
 * published to by a client.
 * @param arguments other properties (construction arguments) for the exchange
 */
Exchange.DeclareOk exchangeDeclare(String exchange,
                                   String type,
                                   boolean durable,
                                   boolean autoDelete,
                                   boolean internal,
                                   Map<String, Object> arguments) throws IOException;

Exchange.DeclareOk exchangeDeclare(String exchange,
                                    BuiltinExchangeType type,
                                    boolean durable,
                                    boolean autoDelete,
                                    boolean internal,
                                    Map<String, Object> arguments) throws IOException;
  • 该方法的作用就是:声明交换机
  • param1:exchange,交换机的名字
    • 必填项
  • param2:type,交换机类型,必填项
    • BuiltinExchangeType是一个枚举类型,包括了所有的可能出现的类型,直接写 string效果一致,可选值为:
    • direct:路由模式(一致性校验)
    • fanout:发布订阅模式(无需绑定)
    • topic:topic模式(模糊匹配)
  • param3:durable,是否持久化交换机
    • false:默认值,不持久化
  • param4:autoDelete,没有消费者使用时,是否自动删除交换机
    • false:默认值,不删除
  • param5:internal,是否内置,如果设置 为true,则表示是内置的交换器, 客户端程序无法直接发送消息到这个交换器中, 只能通过交换器路由到交换器的方式
    • false:默认值,允许外部直接访问
    • 一般不设置此项
  • param6:arguments,交换机的一些其他属性,默认值为 null

channel.queueBind()

/**
 * @param queue the name of the queue
 * @param exchange the name of the exchange
 * @param routingKey the routing key to use for the binding
 * @param arguments other properties (binding parameters)
 */
Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;
  • 该方法的作用是:将队列与交换机进行绑定
  • param1:queue,队列的名字,必填
  • param2:exchange,交换机的名字,必填
  • param3:routingKey,路由的key,用于绑定的路由密钥,发布订阅模式可填为 “”
  • param4:arguments,绑定时可传的参数,默认值为 null

RabbitMQ通讯模型系列

RabbitMQ从零开始学(二)—通信模型之HelloWorld型—channel方法参数详解
RabbitMQ从零开始学(三)—通信模型之Work型—channel.basicQos()
RabbitMQ从零开始学(五)—通信模型之路由模型(direct)
RabbitMQ从零开始学(六)—通信模型之topic模型—通信模型总结

你可能感兴趣的:(RabbitMQ,交换机,rabbitmq,队列,java)