RabbitMQ消息队列(二): 工作队列
1. 工作队列:
对于资源密集型任务,我们等待其处理完成在很多情况下是不现实的,比如无法在http的短暂请求窗口中处理大量耗时任务,
为了达到主线程无需等待,任务异步执行的要求,我们可以将任务加入任务队列,如图,多个workers可以共享
同一个任务队列,同时对任务进行处理,主线程P将延后任务发送到队列之后即可返回,延迟任务由C1和C2处理完成;

2. 轮询调度:
队列会将消息轮询分发给worker,如上图两个worker,则首先发送消息到C1,然后发送消息到C2,然后在发送消息到C1,C2,C1...,
队列按顺序发送,这样保证了每个worker收到的消息是均等的,默认设置情况下,队列并不会考虑worker当前的负载情况。
3. 均衡调度:
如2中所说,比如现在有两个队列,奇数消息都需要队列做大量繁重的处理,而偶数消息则需要处理的逻辑非常少,这样就会造成某个队列
任务繁重,等待处理任务过多,从而使消息处理不均衡,处理能力下降。面对这样的情况,RabbitMQ提供了均衡调度机制,指定worker
只能接收一条消息,当worker处理完毕,队列收到消息确认(4中描述)的时候,才会派发给该worker一条新消息。由此,达到对消息和队列处理能力的均衡调度。
如下,我们可以使用basic_qos,并将perfetch_count设置为1,来告诉队列每次只发送一条消息给当前worker,直到收到完成确认才发下一条。
channel.basic_qos(prefetch_count=1)
4. 消息确认:
当不使用消息确认的情况下,队列将消息投递给worker之后,会立即将消息从队列内存中删除;此时,如果woker被停掉或者崩溃,
那么worker当前正在处理的消息和队列已经派发给worker的消息都会丢失。
RabbitMQ提供了消息确认机制,worker完成处理消息之后发送ack,队列确认消息已处理完毕,才将其从内存中删除。但是这个过程没有
超时,哪怕woker处理了很长时间也是没问题的。当worker挂掉,队列没有收到消息ack,如果有其他worker在运行,那么worker
会将未确认的消息派发给其他运行中的worker。ack确认机制默认是开启的,当然可以在channel中关闭。
注意,一定要确保在消息处理完成之后发送ack,否则队列内存将会随消息的增加而不断增加,甚至造成内存耗尽。
5. 消息持久化:
消息ack解决了worker挂掉时候消息的安全性,但是无法针对整个服务的重启或者挂掉,当RabbitMQ重启或者挂掉的时候,队列和消息都会消失,
为了避免这种情况发生,我们需要设置队列和消息持久化。
(1) 设置队列持久化:durable=True
channel.queue_declare(queue='task_queue', durable=True)
(2) 设置消息持久化:delivery_mode=2
channel.basic_publish(exchange='',
routing_key="task_queue",
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # make message persistent
))
上述设置虽然一定程度上保证了消息持久化,但是在收到消息和持久化消息之间仍然有时间窗口存在,且并不是每条消息都会写一次磁盘,
所以这个时间窗口内仍然可能丢失消息,如果要确保持久化足够健壮,请参考 https://www.rabbitmq.com/confirms.html
6. 测试代码:
new_task.py--用于发送消息到队列
#!/usr/bin/env python
import pika
import sys connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() # 设置队列持久化
channel.queue_declare(queue='task_queue', durable=True) message = ' '.join(sys.argv[1:]) or "Hello World!"
channel.basic_publish(exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # 设置消息持久化
))
print(" [x] Sent %r" % message)
connection.close()
worker.py--用于接收队列消息并完成消息处理
#!/usr/bin/env python
import pika
import time connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() # 设置队列持久化
channel.queue_declare(queue='task_queue', durable=True)
print(' [*] Waiting for messages. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
time.sleep(body.count(b'.'))
print(" [x] Done")
# 完成消息处理,发送ack确认消息
ch.basic_ack(delivery_tag = method.delivery_tag) # 最多同时接受一条消息
channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback,
queue='task_queue') channel.start_consuming()
RabbitMQ消息队列(二): 工作队列的更多相关文章
- .net core使用rabbitmq消息队列 (二)
之前有写过.net core集成使用rabbitmq的博文,见.net core使用rabbitmq消息队列,但是里面的使用很简单,而且还有几个bug,想改下,但是后来想了想,还是算了,之前使用的是. ...
- RabbitMQ 消息队列 二
一:查看MQ的用户角色 rabbitmqctl list_users 二:添加新的角色,并授予权限 rabbitmqctl add_user xiaoyao 123456 rabbitmqctl se ...
- .net core使用rabbitmq消息队列
看博文的朋友,本文有些过时了,还有些BUG,如果想了解更多用法,看看这篇吧:.net core使用rabbitmq消息队列 (二) 首先,如果你还没有安装好rabbitmq,可以参考我的博客: Ubu ...
- RabbitMQ消息队列系列教程(二)Windows下安装和部署RabbitMQ
摘要 本篇经验将和大家介绍Windows下安装和部署RabbitMQ消息队列服务器,希望对大家的工作和学习有所帮助! 目录 一.Erlang语言环境的搭建 二.RabbitMQ服务环境的搭建 三.Ra ...
- RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列
一.理论: .net环境下,C#代码调用RabbitMQ消息队列,本文用easynetq开源的.net Rabbitmq api来实现. EasyNetQ 是一个易于使用的RabbitMQ的.Net客 ...
- (十二)RabbitMQ消息队列-性能测试
原文:(十二)RabbitMQ消息队列-性能测试 硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5 ...
- (二)RabbitMQ消息队列-RabbitMQ消息队列架构与基本概念
原文:(二)RabbitMQ消息队列-RabbitMQ消息队列架构与基本概念 没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. Rabbit ...
- RabbitMQ消息队列(二)-RabbitMQ消息队列架构与基本概念
没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. RabbitMQ架构 说是架构其实更像是应用场景下的架构(自己画的有点丑,勿嫌弃) 从图中 ...
- RabbitMQ基本概念(二)-RabbitMQ消息队列架构与基本概念
没错我还是没有讲怎么安装和写一个HelloWord,不过快了,这一章我们先了解下RabbitMQ的基本概念. RabbitMQ架构 说是架构其实更像是应用场景下的架构(自己画的有点丑,勿嫌弃) 从图中 ...
- RabbitMQ六种队列模式-工作队列模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列 [本文]RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
随机推荐
- 第三十篇 面向对象的三大特性之继承 supre()
继承 一 .什么是继承? 类的继承跟现实生活中的父.子.孙子.重孙子的继承关系一样,父类又称基类. Python中类的继承分为:单继承 和 多继承. # 定义父类 class ParentClass ...
- ASP NET Core --- HTTP 翻页、过滤、排序
参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/v07647j3zkq.html 翻页, 过滤, 排序等 – 如何传递参数? Query ...
- [CH5302]金字塔
题面 虽然探索金字塔是极其老套的剧情,但是有一队探险家还是到了某金字塔脚下.经过多年的研究,科学家对这座金字塔的内部结构已经有所了解.首先,金字塔由若干房间组成,房间之间连有通道.如果把房间看作节点, ...
- BZOJ 2333 SCOI2011 棘手的操作 并查集+可并堆
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2333 ..题意概述就不写了,各位老爷如果是看着玩的可以去搜一下,如果是做题找来的也知道题干 ...
- 【工作感悟】——揭开“PM”的面纱
[前言] 上次跟大家分享了面试的故事,小编觉得效果还不错,因此小编决定把工作感悟系列写下去,不过时间就不好说了.希望小伙伴们在评论列表中发表自己的看法和观点,积极参与啦~~ [背景] 初来Y公司,作为 ...
- well-known file is not secure
执行jstack pid时,提示well-known file is not secure. 原因是pid的启动用户不是当前用户,需要切换到启动用户下执行jstack即可. 可以通过如下命令来处理: ...
- 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap
题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义 ...
- [洛谷P3693]琪露诺的冰雪小屋
题目大意:琪露诺的冰雪小屋,我做的第一道大模拟题. 题解:模拟... 卡点:无数小错误,要是没有写一点调一点,那大概是永远调不出来了... C++ Code: #include <cstdio& ...
- java一个接口可以继承另外一个接口吗
一个接口可以继承多个接口. interface C extends A, B {}是可以的. 一个类可以实现多个接口: class D implements A,B,C{} 但是一个类只能继承一个类, ...
- 用原生JavaScript做个简单的回到顶部
很多网页在下方都会放置一个“返回顶部”按钮,尤其是页面底部没有导航的网页,这样可以帮助访客重新找到导航或者重温一遍广告(想得真美).随着近几年来 JavaScript 的应用日渐广泛,滑动效果无处不在 ...