RabbitMQ的七种工作模式-工作模式(二)

2.工作模式
一个生产者,多个消费者,不涉及Exchange
在这里插入图片描述
工作模式的优点是,在供大于求或供不应求的情况下,可插拔消费者。

消息生产者:

    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.MessageProperties;
    
    /**
     * @author Becolette
     * @description 请注明类功能
     * @datetime 2020/9/24 15:32
     */
    public class NewTask {
    
        private static final String TASK_QUEUE_NAME = "task_queue";
    
        public static void main(String[] argv) throws Exception {
            ConnectionFactory factory = new ConnectionFactory();
            /**
             * 此处是采用了默认的配置,可以ctrl + F3进入ConnectionFactory配置连接参数查看
             * 下列的factory.setHost("localhost")相当于
             *         factory.setHost("localhost")
             *         factory.setPort(5672)
             *         factory.setUsername("guest")
             *         factory.setPassword("guest")
             *         factory.setVirtualHost("/")
             */
            factory.setHost("localhost");
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
            try {
    
                /**
                 * 参考简单模式对应参数说明
                 * durable 当前保持持久化
                 */
                channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
    
                /** join是拼接数据为字符串,这里我修改了一下,来个循环发送消息
                 * String message = String.join(" ", argv)
                 */
                for (int i = 0; i < 100; i++) {
                    String message = "消息体" + i;
                    /**
                     * MessageProperties.PERSISTENT_TEXT_PLAIN:消息永久保存直到被消费
                     */
                    channel.basicPublish("", TASK_QUEUE_NAME,
                            MessageProperties.PERSISTENT_TEXT_PLAIN,
                            message.getBytes("UTF-8"));
                    System.out.println(" [x] Sent '" + message + "'");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }

消息消费者公用方法:

        public static void recv() throws Exception {
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            /** 声明通道,接受消息 */
            channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
            System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
    
            channel.basicQos(1);
    
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
    
                /**
                 * @see com.rabbitmq.client.AMQP.Basic.Ack
                 * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk}
                 *                    or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
                 *                    标签可以从GetOk或Deliver种获取
                 * @param multiple true to acknowledge all messages up to and
                 * including the supplied delivery tag; false to acknowledge just
                 * the supplied delivery tag.
                 *                 如果true则消息和标签一起返回,否则返回标签
                 */
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    
                /** 如果要形成交替输出,可以加等待时间 */
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            /** 参考简单模式参数说明 */
            channel.basicConsume(TASK_QUEUE_NAME, false, deliverCallback, consumerTag -> {
            });
        }

建立两个消费者类WokRecv1,WorkRecv2,调用如下:

CommonRecv.recv();

该模式引出三个重点-消息确认:

1.自动模式

消费者从消息队列拿走信息之后,服务端就认为消息被成功消费

2.手动模式

消费者从消息队列获取消息后,服务端并没有标记为成功消费

消费者成功消费后需要将状态返回到服务端

手动模式处理方式:

1.如果消息被正常处理,返回确认信息,队列中删除该消息

2.如果消息正常发出,但是因为确认信息返回丢失,连接被关闭或是TCP连接关闭,则对消息进行重新排队,或则交付给其他消费者处理

3.如果消息消费者不存在,则会一直等到消息被消费

以上是消息确认中的手动确认方式,默认是打开状态,可以用autoAck=true关闭手动确认。

手动确认的优缺点:

优点:保证在消息没有正常消费的情况下,队列中不能被删除,保证消息的准确完整消费

缺点:消费未被消费会不断堆积,导致内存溢出

(Linux:sudo rabbitmqctl list_queues name messages_ready messages_unacknowledged

Windows:rabbitmqctl.bat list_queues name messages_ready messages_unacknowledged)

消息持久化

保证消费者死亡,任务也不会丢失;需要将队列和消息都标记为持久。但不能完全保证,因为消息有可能消费很快,或则在写入磁盘时断电,会丢失数据,但情况很少出现

消息公平消费

保证不会有的消费者很忙,有的却很空闲,出现饥饿或是过饱现象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值