zoukankan      html  css  js  c++  java
  • RabbitMQ五种消息队列学习(三)–Work模式

    由于在实际应用中,简单队列模型无法解决很多实际问题,而且生产者和消费者是一对一的关系。模型较为单一。故引入Work模式。

    结构图

    这里写图片描述

    一个生产者、多个消费者。 
    一个消息只能被一个消费者获取。

    测试实现: 
    1、生产者

     private final static String QUEUE_NAME = "test_queue_work";
    
        public static void main(String[] argv) throws Exception {
            // 获取到连接以及mq通道
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
    
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    
            for (int i = 0; i < 50; i++) {
                // 消息内容
                String message = "" + i;
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
                System.out.println(" [x] Sent '" + message + "'");
    
                Thread.sleep(i * 10);
            }
    
            channel.close();
            connection.close();
        }

    生产者循环创建消息 
    2、消费者一

    private final static String QUEUE_NAME = "test_queue_work";
    
        public static void main(String[] argv) throws Exception {
    
            // 获取到连接以及mq通道
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
    
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    
            // 同一时刻服务器只会发一条消息给消费者
            channel.basicQos(1);
    
            // 定义队列的消费者
            QueueingConsumer consumer = new QueueingConsumer(channel);
            // 监听队列,手动返回完成
            channel.basicConsume(QUEUE_NAME, false, consumer);
    
            // 获取消息
            while (true) {
                QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                String message = new String(delivery.getBody());
                System.out.println(" [x] Received '" + message + "'");
                //休眠
                Thread.sleep(10);
                // 返回确认状态
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            }
        }

    3、消费者二 
    注意:channel.basicQos(1); 被注释掉了

    private final static String QUEUE_NAME = "test_queue_work";
    
        public static void main(String[] argv) throws Exception {
    
            // 获取到连接以及mq通道
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
    
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    
            // 同一时刻服务器只会发一条消息给消费者
           // channel.basicQos(1);
    
            // 定义队列的消费者
            QueueingConsumer consumer = new QueueingConsumer(channel);
            // 监听队列,手动返回完成状态
            channel.basicConsume(QUEUE_NAME, false, consumer);
    
            // 获取消息
            while (true) {
                QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                String message = new String(delivery.getBody());
                System.out.println(" [x] Received '" + message + "'");
                // 休眠1秒
                Thread.sleep(1000);
    
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            }
        }

    测试结果:

    1、 消费者1和消费者2获取到的消息内容是不同的,同一个消息只能被一个消费者获取。 
    2、 消费者1和消费者2获取到的消息的数量是相同的,一个是奇数一个是偶数。

    其实,这样是不合理的,应该是消费者1要比消费者2获取到的消息多才对。

    消息的确认模式

    消费者从队列中获取消息,服务端如何知道消息已经被消费呢?

    模式1:自动确认

    只要消息从队列中获取,无论消费者获取到消息后是否成功消息,都认为是消息已经成功消费。

    模式2:手动确认

    消费者从队列中获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,如果消费者一直没有反馈,那么该消息将一直处于不可用状态。

    应用场景

    集群中同时监听一个服务队列
  • 相关阅读:
    公司内部图书管理界面原型设计图
    对象的判等
    虚方法的调用
    类的初始化顺序
    A good idea: TotT – Testing on the Toilet
    变量命名
    QSignalMapper
    dxsdk出错,代码写完后按这个solution试下
    SVG 我太土了。。
    gsl在vc下编译时一个问题
  • 原文地址:https://www.cnblogs.com/shanheyongmu/p/10406155.html
Copyright © 2011-2022 走看看