RabbitMQ之工作队列
工作队列
工作队列(又称:任务队列Task Queues)是为了避免等待一些占用大量资源、时间的操作,当我们把任务Task当做消息发送队列中,一个运行在后台的工作者worker进程就会取出任务然后处理。
当有多个works,任务在它们之间共享
创建任务
创建任务的new_task.py
#!/usr/bin/env python
#-*- coding:utf8 -*-
import sys
import pika
import logging logging.basicConfig(format='%(levlename)s:%(message)s',level=logging.CRITICAL) def send():
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel() #创建一个队列,并且设置队列可以持久化,durable=True
channel.queue_declare(queue='task_queue',durable=True) #将输入参数按照.号串联起来,后续在消费的时候每个点都sleep一秒钟
if len(sys.argv) == 1:
message = "Hello World!"
else:
message = '.'.join(sys.argv[1]) #向队列task_queue发送消息,routing_key指定,与queue_declare中对应
#发送消息为message,对应参数body
#设置消息持久化
channel.basic_publish(exchange='',
routing_key = 'task_queue',
body = message,
properties = pika.BasicProperties(delivery_mode=2),
)
print " [x] Send %r" % (message,) connection.close() if __name__ == '__main__':
send()
需要重点说明:
1、消息队列持久化,设置channel.queue_declare中durable参数为True,这样在RabbitMQ-server重启之后,消息不会丢失
2、消息持久化,设置delivery_mode等于2
消息持久化
将消息持久化并不能完全保证不会丢失,以上代码只是告诉RabbitMQ要把消息存放到磁盘上,但是从RabbitMQ收到消息到保存之间还存在很小的时间间隔。RabbitMQ并不是所有的消息都使用fsync(2),可能保存到缓存中,并不一定会写到磁盘中。并不能保证真正的持久化,但可以应付简单的队列工作。
如果需要持久化,需要修改代码支持事务。
执行任务
执行任务,通过work.py来操作
#!/usr/bin/env python
#-*-coding:utf8 -*- import pika
import time def callback(ch, method, properties, body):
print " [x] Received %r" % (body,) #每遇到一个点,就sleep一秒钟,模拟长时间任务
sleep_time = body.count('.')*100
print "slepp_time=%d" % sleep_time time.sleep(body.count('.')*100) print " [x] Done" #任务执行完成之后返回确认包
#这样对于没有返回确认包的消息就不会丢失
ch.basic_ack(delivery_tag= method.delivery_tag) def work():
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel() channel.queue_declare(queue='task_queue',durable=True) print "[*] Wating for messages.To exit press CTRL+C" #保证消息的公平分发,设置prefetch告诉同一时刻,不要发送超过1条消息给一个工作者
#直到它已经处理上一条消息并且做出响应
channel.basic_qos(prefetch_count=1) #开始消费消息
channel.basic_consume(callback,queue='task_queue') #循环消费
#channel.start_consuming() if __name__ == '__main__':
try:
work()
except KeyboardInterrupt,e:
print "Exit"
重点说明
1、使用工作队列的一个好处就是能够并行的处理队列。如果任务堆积,只需要添加更多的工作者work即可
2、对于多个work,RabbitMQ会按照顺序把消息发送给每个消费者,这种方式为轮询(round-robin)
3、消息响应:如果一个work挂掉,上面代码实现将这个消息发送给其他work,而不是丢弃。
因此需要消息响应机制,每个work处理完成任务的时候,会发送一个ack,告诉RabbitMQ-server已经收到并处理某条消息,然后RabbitMQ-server释放并删除这条消息。
4、消息ack没有超时的概念,这样在处理一个非常耗时的消息任务时候就不会出现问题
5、消息ack默认是开启的,通过no_ack=True标识关闭,在回调函数中basic_ack中
6、如果忘记调用basic_ack的话,这样消息在程序退出后重新发送,会导致RabbitMQ-server中消息堆积,占用越来越多的内存。通过如下命令进行确认:
guosong@guosong:~/code/rabbitmq/ch2$ rabbitmqctl list_queues name messages_ready messages_unacknowledged
Listing queues ...
task_queue 3 0
...done.
存在三个堆积的任务
7、关于队列大小:如果所有的工作者都在处理任务,队列就会被填满。需要留意这个问题,要么添加更多的工作者,要么使用其他策略,例如设置队列大小等。
send和receive
ChannelClosed: (406, "PRECONDITION_FAILED - parameters for queue 'rt_test_dba_queue' in vhost '/' not equivalent")
(406, "PRECONDITION_FAILED - parameters for queue 'rt_test_dba_queue' in vhost '/' not equivalent")
参考链接
http://adamlu.net/rabbitmq/tutorial-two-python
https://pika.readthedocs.org/en/latest/modules/index.html
RabbitMQ之工作队列的更多相关文章
- 【译】RabbitMQ:工作队列(Work Queue)
在第一篇我们写了两个程序通过一个命名的队列分别发送和接收消息.在这一篇,我们将创建一个工作队列在多个工作线程间分发耗时的工作任务. 工作队列的核心思想是避免立刻处理资源密集型任务导致必须等待其执行完成 ...
- RabbitMQ的工作队列和路由
工作队列:Working Queue 工作队列这个概念与简单的发送/接收消息的区别就是:接收方接收到消息后,可能需要花费更长的时间来处理消息,这个过程就叫一个Work/Task. 几个概念 分 ...
- RabbitMQ 笔记-工作队列
工作队列的主要思想是不用等待资源密集型的任务处理完成, 为了确保消息或者任务不会丢失,rabbitmq 支持消息确信 ACK.ACK机制是消费者端从rabbitmq收到消息并处理完成后,反馈给rabb ...
- RabbitMQ (四) 工作队列之公平分发
上篇文章讲的轮询分发 : 1个队列,无论多少个消费者,无论消费者处理消息的耗时长短,大家消费的数量都一样. 而公平分发,又叫 : 能者多劳,顾名思义,处理得越快,消费得越多. 生产者 public c ...
- RabbitMQ (三) 工作队列之轮询分发
上一篇讲了简单队列,实际工作中,这种队列应该很少用到,因为生产者发送消息的耗时一般都很短,但是消费者收到消息后,往往伴随着对高消息的业务逻辑处理,是个耗时的过程,这势必会导致大量的消息积压在一个消费者 ...
- RabbitMQ学习笔记(二) 工作队列
什么是工作队列? 工作队列(又名任务队列)是RabbitMQ提供的一种消息分发机制.当一个Consumer实例正在进行资源密集任务的时候,后续的消息处理都需要等待这个实例完成正在执行的任务,这样就导致 ...
- RabbitMQ入门(二)工作队列
在文章RabbitMQ入门(一)之Hello World,我们编写程序通过指定的队列来发送和接受消息.在本文中,我们将会创建工作队列(Work Queue),通过多个workers来分配耗时任务. ...
- .NET Core RabbitMQ探索(1)
RabbitMQ可以被比作一个邮局,当你向邮局寄一封信时,邮局会保证将这封信送达你写的收件人,而RabbitMQ与邮局最主要的区别是,RabbitMQ并不真的处理信件,它处理的是二进制的数据块,它除了 ...
- 消息中间件-RabbitMQ基本使用
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件).RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的.所有主要 ...
随机推荐
- 翻译连载 | 第 10 章:异步的函数式(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...
- NOIP初赛 之 哈夫曼树
哈夫曼树 种根据我已刷的初赛题中基本每套的倒数第五或第六个不定项选择题就有一个关于哈夫曼树及其各种应用的题,占:0-1.5分:然而我针对这个类型的题也多次不会做,so,今晚好好研究下哈夫曼树: 概念: ...
- python3.6安装pyspider
win10下安装pyspider 1.pip 我在安装pip的时候默认安装了Pip. 如果没有的话:pip安装 2.PhantomJS PhantomJS 是一个基于 WebKit 的服务器端 Jav ...
- spring cloud+dotnet core搭建微服务架构:配置中心续(五)
前言 上一章最后讲了,更新配置以后需要重启客户端才能生效,这在实际的场景中是不可取的.由于目前Steeltoe配置的重载只能由客户端发起,没有实现处理程序侦听服务器更改事件,所以还没办法实现彻底实现这 ...
- win10 uwp 打电话
UWP可以使用打电话功能,在PC是用Skype,在手机是直接使用电话功能. UWP可以通过Skype打电话,那么如何通过应用间通讯,很简单使用Launcher. Skype电话使用Skype:(电话号 ...
- vue——实例方法 / 数据
目录 1.vm.$set 2.vm.$watch 3.vm.$delete 1.vm.$set 哎呀呀,周五啦,大家应该都很开心吧,放假了可以好好休息休息啦,然而小颖明天要面试,所以小颖今天就回去放了 ...
- UVa225,Golygons
刘儒家翻译的走出的图形可以自交,不知道大家是怎么理解的,反正我是认为这句话的意思是告诉我允许一个点访问多次 这样是WA的,n=15和n=16时多输出很多数据,应该是不允许自交,也就是不允许一个点访问多 ...
- (扩展根目录容量方法汇总)把Linux系统迁移到另一个分区或者硬盘
Linux系统扩容方法汇总 相信很多朋友都有过这样的经历,本想装个Ubantu玩玩,没想到玩久了反而不习惯Windows了,然而开始装系统的时候只分配了非常小的空间,那应该怎样扩展我们的ubantu呢 ...
- java基础解析系列(九)---String不可变性分析
java基础解析系列(九)---String不可变性分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---In ...
- 磨刀不误砍柴工!vs2010快捷键大全
最常用的快捷键: VS2012变化的快捷键: 注释::VS2010是(Ctrl+E,C),VS2012是(Ctrl+K, Ctrl+C),实际操作,按住Ctrl键不放,先按K键,再按C键.相当于Ctr ...