Bootstrap

RabbitMQ4:work模型

欢迎来到“雪碧聊技术”CSDN博客!

在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目心得。

让我们一同在Java的广阔天地中遨游,携手提升技术能力,共创美好未来!感谢您的关注与支持,期待在“雪碧聊技术”与您共同成长!

目录

一、work模型?

1、什么是work模型?

2、案例

①案例介绍

②具体操作

③观察上述现象:无论两个消费者的消费速度一致,还是不一致,最终二者消费的消息数量都是25条(平分,一人从队列取一半)。

3、为何会出现上述问题?

4、如何解决上述问题?

5、根据上述的思路,解决该问题

二、总结

1、知识总结

2、面试题:如何避免消息堆积问题?

①给队列上绑定多个消费者(work模型),从而提高消费速度

②优化代码,使代码执行速度变快,消费速度也就变快了

③rabbitMQ的默认规则:队列中的同一条消息,只能被一个消费者消费。即:不会出现两个消费者消费同一条消息的现象,从而提高消费速度。

④通过设置prefetch,来控制消费者手里最多有1条消息,不允许堆积消息,实现能者多劳。(最重要的一点)


一、work模型?

1、什么是work模型?

        work queues,是一种任务模型。简单来说就是让多个消费者绑定到一个队列,共同消费队列中的消息。

        注意:rabbitMQ默认同一条消息只能被一个消费者消费。

        即:不会出现两个消费者消费同一条消息的现象。

2、案例

①案例介绍

②具体操作

  • 第一步:创建一个队列work.queue

  • 第二步:编写生产者代码,1秒的时间,向队列work.queue发送50条消息

运行结果:

  • 第三步:编写监听者代码,监听队列work.queue的消息
@Component //交给spring管理
public class MqListener {

    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue1(String msg){//消费者1
        System.out.println("消费者1 收到了 work.queue的消息... :【" + msg + "】");
    }

    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue2(String msg){//消费者2
        System.err.println("消费者2 收到了 work.queue的消息... :【" + msg + "】");
    }
    
}

运行结果:

消费者1 收到了 work.queue的消息... :【hello, work, message_1】
消费者2 收到了 work.queue的消息... :【hello, work, message_2】
消费者1 收到了 work.queue的消息... :【hello, work, message_3】
消费者2 收到了 work.queue的消息... :【hello, work, message_4】
消费者1 收到了 work.queue的消息... :【hello, work, message_5】
消费者2 收到了 work.queue的消息... :【hello, work, message_6】
消费者1 收到了 work.queue的消息... :【hello, work, message_7】
消费者2 收到了 work.queue的消息... :【hello, work, message_8】
消费者1 收到了 work.queue的消息... :【hello, work, message_9】
消费者2 收到了 work.queue的消息... :【hello, work, message_10】
消费者1 收到了 work.queue的消息... :【hello, work, message_11】
消费者2 收到了 work.queue的消息... :【hello, work, message_12】
消费者1 收到了 work.queue的消息... :【hello, work, message_13】
消费者2 收到了 work.queue的消息... :【hello, work, message_14】
消费者1 收到了 work.queue的消息... :【hello, work, message_15】
消费者2 收到了 work.queue的消息... :【hello, work, message_16】
消费者1 收到了 work.queue的消息... :【hello, work, message_17】
消费者2 收到了 work.queue的消息... :【hello, work, message_18】
消费者1 收到了 work.queue的消息... :【hello, work, message_19】
消费者2 收到了 work.queue的消息... :【hello, work, message_20】
消费者1 收到了 work.queue的消息... :【hello, work, message_21】
消费者2 收到了 work.queue的消息... :【hello, work, message_22】
消费者1 收到了 work.queue的消息... :【hello, work, message_23】
消费者2 收到了 work.queue的消息... :【hello, work, message_24】
消费者1 收到了 work.queue的消息... :【hello, work, message_25】
消费者2 收到了 work.queue的消息... :【hello, work, message_26】
消费者1 收到了 work.queue的消息... :【hello, work, message_27】
消费者2 收到了 work.queue的消息... :【hello, work, message_28】
消费者1 收到了 work.queue的消息... :【hello, work, message_29】
消费者2 收到了 work.queue的消息... :【hello, work, message_30】
消费者1 收到了 work.queue的消息... :【hello, work, message_31】
消费者2 收到了 work.queue的消息... :【hello, work, message_32】
消费者1 收到了 work.queue的消息... :【hello, work, message_33】
消费者2 收到了 work.queue的消息... :【hello, work, message_34】
消费者1 收到了 work.queue的消息... :【hello, work, message_35】
消费者2 收到了 work.queue的消息... :【hello, work, message_36】
消费者1 收到了 work.queue的消息... :【hello, work, message_37】
消费者2 收到了 work.queue的消息... :【hello, work, message_38】
消费者1 收到了 work.queue的消息... :【hello, work, message_39】
消费者2 收到了 work.queue的消息... :【hello, work, message_40】
消费者1 收到了 work.queue的消息... :【hello, work, message_41】
消费者2 收到了 work.queue的消息... :【hello, work, message_42】
消费者1 收到了 work.queue的消息... :【hello, work, message_43】
消费者2 收到了 work.queue的消息... :【hello, work, message_44】
消费者1 收到了 work.queue的消息... :【hello, work, message_45】
消费者2 收到了 work.queue的消息... :【hello, work, message_46】
消费者1 收到了 work.queue的消息... :【hello, work, message_47】
消费者2 收到了 work.queue的消息... :【hello, work, message_48】
消费者1 收到了 work.queue的消息... :【hello, work, message_49】
消费者2 收到了 work.queue的消息... :【hello, work, message_50】

由于此时两个消费者的消费速度一致(因为方法代码量相同),因此一人消费25条消息。 

  • 第四步:我们让这两个消费者的消费速度一个快,一个慢

运行结果:

消费者1 收到了 work.queue的消息... :【hello, work, message_1】
消费者2 收到了 work.queue的消息... :【hello, work, message_2】
消费者1 收到了 work.queue的消息... :【hello, work, message_3】
消费者1 收到了 work.queue的消息... :【hello, work, message_5】
消费者1 收到了 work.queue的消息... :【hello, work, message_7】
消费者2 收到了 work.queue的消息... :【hello, work, message_4】
消费者1 收到了 work.queue的消息... :【hello, work, message_9】
消费者1 收到了 work.queue的消息... :【hello, work, message_11】
消费者1 收到了 work.queue的消息... :【hello, work, message_13】
消费者1 收到了 work.queue的消息... :【hello, work, message_15】
消费者2 收到了 work.queue的消息... :【hello, work, message_6】
消费者1 收到了 work.queue的消息... :【hello, work, message_17】
消费者1 收到了 work.queue的消息... :【hello, work, message_19】
消费者1 收到了 work.queue的消息... :【hello, work, message_21】
消费者2 收到了 work.queue的消息... :【hello, work, message_8】
消费者1 收到了 work.queue的消息... :【hello, work, message_23】
消费者1 收到了 work.queue的消息... :【hello, work, message_25】
消费者1 收到了 work.queue的消息... :【hello, work, message_27】
消费者1 收到了 work.queue的消息... :【hello, work, message_29】
消费者2 收到了 work.queue的消息... :【hello, work, message_10】
消费者1 收到了 work.queue的消息... :【hello, work, message_31】
消费者1 收到了 work.queue的消息... :【hello, work, message_33】
消费者1 收到了 work.queue的消息... :【hello, work, message_35】
消费者2 收到了 work.queue的消息... :【hello, work, message_12】
消费者1 收到了 work.queue的消息... :【hello, work, message_37】
消费者1 收到了 work.queue的消息... :【hello, work, message_39】
消费者1 收到了 work.queue的消息... :【hello, work, message_41】
消费者2 收到了 work.queue的消息... :【hello, work, message_14】
消费者1 收到了 work.queue的消息... :【hello, work, message_43】
消费者1 收到了 work.queue的消息... :【hello, work, message_45】
消费者1 收到了 work.queue的消息... :【hello, work, message_47】
消费者1 收到了 work.queue的消息... :【hello, work, message_49】
消费者2 收到了 work.queue的消息... :【hello, work, message_16】
消费者2 收到了 work.queue的消息... :【hello, work, message_18】
消费者2 收到了 work.queue的消息... :【hello, work, message_20】
消费者2 收到了 work.queue的消息... :【hello, work, message_22】
消费者2 收到了 work.queue的消息... :【hello, work, message_24】
消费者2 收到了 work.queue的消息... :【hello, work, message_26】
消费者2 收到了 work.queue的消息... :【hello, work, message_28】
消费者2 收到了 work.queue的消息... :【hello, work, message_30】
消费者2 收到了 work.queue的消息... :【hello, work, message_32】
消费者2 收到了 work.queue的消息... :【hello, work, message_34】
消费者2 收到了 work.queue的消息... :【hello, work, message_36】
消费者2 收到了 work.queue的消息... :【hello, work, message_38】
消费者2 收到了 work.queue的消息... :【hello, work, message_40】
消费者2 收到了 work.queue的消息... :【hello, work, message_42】
消费者2 收到了 work.queue的消息... :【hello, work, message_44】
消费者2 收到了 work.queue的消息... :【hello, work, message_46】
消费者2 收到了 work.queue的消息... :【hello, work, message_48】
消费者2 收到了 work.queue的消息... :【hello, work, message_50】

③观察上述现象:无论两个消费者的消费速度一致,还是不一致,最终二者消费的消息数量都是25条(平分,一人从队列取一半)。

3、为何会出现上述问题?

        rabbitMQ的队列,默认轮询给两个消费者分配消息,而不管消费者的消费速度。该问题的关键是消费者手里还能存储消息,即消费不完的可以存下来,慢慢消费。这就导致了两个消费者平分消息的现象。

        类比:一个大人,一个小孩,一起吃苹果。苹果摊老板不管这两个人吃苹果的速度,只是轮流给两个人发苹果,并且大人和小孩是可以存储还没消费完的苹果,最终导致一共50个苹果,一人发了25个。即:小孩虽然吃得慢,但是兜里能揣啊,于是堆积在手里,一点一点吃。最终小孩还是能分到一半的苹果。

       

4、如何解决上述问题?

        解决方案:消费者消息推送限制

        说白了就是,你吃苹果吃得慢是吧,那我不让你存苹果了,而是让你吃完手里的一个,再拿一个。

         根据上述配置,限制了消费者手里只能留一个消息,即:不让消费者再堆积还没消费的消息了。

        类比:此时苹果摊老板,仍然是轮流给两人发苹果,只不过现在多了一条规矩:手里苹果还没吃完的人,就不给他发苹果了,吃完手里那个苹果的人才能再拿一个苹果。这样就限制了小孩堆积苹果的现象。也就解决了上述问题。

5、根据上述的思路,解决该问题

改进问题后,运行代码:

消费者1 收到了 work.queue的消息... :【hello, work, message_1】
消费者2 收到了 work.queue的消息... :【hello, work, message_2】
消费者1 收到了 work.queue的消息... :【hello, work, message_3】
消费者1 收到了 work.queue的消息... :【hello, work, message_4】
消费者1 收到了 work.queue的消息... :【hello, work, message_5】
消费者1 收到了 work.queue的消息... :【hello, work, message_6】
消费者1 收到了 work.queue的消息... :【hello, work, message_7】
消费者1 收到了 work.queue的消息... :【hello, work, message_8】
消费者1 收到了 work.queue的消息... :【hello, work, message_9】
消费者2 收到了 work.queue的消息... :【hello, work, message_10】
消费者1 收到了 work.queue的消息... :【hello, work, message_11】
消费者1 收到了 work.queue的消息... :【hello, work, message_12】
消费者1 收到了 work.queue的消息... :【hello, work, message_13】
消费者1 收到了 work.queue的消息... :【hello, work, message_14】
消费者1 收到了 work.queue的消息... :【hello, work, message_15】
消费者1 收到了 work.queue的消息... :【hello, work, message_16】
消费者1 收到了 work.queue的消息... :【hello, work, message_17】
消费者2 收到了 work.queue的消息... :【hello, work, message_18】
消费者1 收到了 work.queue的消息... :【hello, work, message_19】
消费者1 收到了 work.queue的消息... :【hello, work, message_20】
消费者1 收到了 work.queue的消息... :【hello, work, message_21】
消费者1 收到了 work.queue的消息... :【hello, work, message_22】
消费者1 收到了 work.queue的消息... :【hello, work, message_23】
消费者1 收到了 work.queue的消息... :【hello, work, message_24】
消费者1 收到了 work.queue的消息... :【hello, work, message_25】
消费者2 收到了 work.queue的消息... :【hello, work, message_26】
消费者1 收到了 work.queue的消息... :【hello, work, message_27】
消费者1 收到了 work.queue的消息... :【hello, work, message_28】
消费者1 收到了 work.queue的消息... :【hello, work, message_29】
消费者1 收到了 work.queue的消息... :【hello, work, message_30】
消费者1 收到了 work.queue的消息... :【hello, work, message_31】
消费者1 收到了 work.queue的消息... :【hello, work, message_32】
消费者1 收到了 work.queue的消息... :【hello, work, message_33】
消费者2 收到了 work.queue的消息... :【hello, work, message_34】
消费者1 收到了 work.queue的消息... :【hello, work, message_35】
消费者1 收到了 work.queue的消息... :【hello, work, message_36】
消费者1 收到了 work.queue的消息... :【hello, work, message_37】
消费者1 收到了 work.queue的消息... :【hello, work, message_38】
消费者1 收到了 work.queue的消息... :【hello, work, message_39】
消费者1 收到了 work.queue的消息... :【hello, work, message_40】
消费者1 收到了 work.queue的消息... :【hello, work, message_41】
消费者2 收到了 work.queue的消息... :【hello, work, message_42】
消费者1 收到了 work.queue的消息... :【hello, work, message_43】
消费者1 收到了 work.queue的消息... :【hello, work, message_44】
消费者1 收到了 work.queue的消息... :【hello, work, message_45】
消费者1 收到了 work.queue的消息... :【hello, work, message_46】
消费者1 收到了 work.queue的消息... :【hello, work, message_47】
消费者1 收到了 work.queue的消息... :【hello, work, message_48】
消费者1 收到了 work.queue的消息... :【hello, work, message_49】
消费者2 收到了 work.queue的消息... :【hello, work, message_50】

可见此时显然不是平分消息,而是能者多劳。

消费者1消费速度快,因此消费了43条消息;

消费者2消费速度慢,因此消费了7条消息。

以上就解决了 忽略消费速度而无脑平分消息的问题。

二、总结

1、知识总结

2、面试题:如何避免消息堆积问题?

①给队列上绑定多个消费者(work模型),从而提高消费速度

②优化代码,使代码执行速度变快,消费速度也就变快了

③rabbitMQ的默认规则:队列中的同一条消息,只能被一个消费者消费。即:不会出现两个消费者消费同一条消息的现象,从而提高消费速度。

④通过设置prefetch,来控制消费者手里最多有1条消息,不允许堆积消息,实现能者多劳。(最重要的一点)

以上就是work模型的全部详细内容,想了解更多的RabbitMQ知识,请关注本博主~~

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;