工作队列

工作队列(又称:任务队列Task Queues)是为了避免等待一些占用大量资源、时间的操作,当我们把任务Task当做消息发送队列中,一个运行在后台的工作者worker进程就会取出任务然后处理。

当有多个works,任务在它们之间共享

创建任务

创建任务的new_task.py

  1. #!/usr/bin/env python
  2. #-*- coding:utf8 -*-
  3. import sys
  4. import pika
  5. import logging
  6.  
  7. logging.basicConfig(format='%(levlename)s:%(message)s',level=logging.CRITICAL)
  8.  
  9. def send():
  10. connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
  11. channel = connection.channel()
  12.  
  13. #创建一个队列,并且设置队列可以持久化,durable=True
  14. channel.queue_declare(queue='task_queue',durable=True)
  15.  
  16. #将输入参数按照.号串联起来,后续在消费的时候每个点都sleep一秒钟
  17. if len(sys.argv) == 1:
  18. message = "Hello World!"
  19. else:
  20. message = '.'.join(sys.argv[1])
  21.  
  22. #向队列task_queue发送消息,routing_key指定,与queue_declare中对应
  23. #发送消息为message,对应参数body
  24. #设置消息持久化
  25. channel.basic_publish(exchange='',
  26. routing_key = 'task_queue',
  27. body = message,
  28. properties = pika.BasicProperties(delivery_mode=2),
  29. )
  30. print " [x] Send %r" % (message,)
  31.  
  32. connection.close()
  33.  
  34. if __name__ == '__main__':
  35. send()

需要重点说明:

1、消息队列持久化,设置channel.queue_declare中durable参数为True,这样在RabbitMQ-server重启之后,消息不会丢失

2、消息持久化,设置delivery_mode等于2

消息持久化

将消息持久化并不能完全保证不会丢失,以上代码只是告诉RabbitMQ要把消息存放到磁盘上,但是从RabbitMQ收到消息到保存之间还存在很小的时间间隔。RabbitMQ并不是所有的消息都使用fsync(2),可能保存到缓存中,并不一定会写到磁盘中。并不能保证真正的持久化,但可以应付简单的队列工作。

如果需要持久化,需要修改代码支持事务。

执行任务

执行任务,通过work.py来操作

  1. #!/usr/bin/env python
  2. #-*-coding:utf8 -*-
  3.  
  4. import pika
  5. import time
  6.  
  7. def callback(ch, method, properties, body):
  8. print " [x] Received %r" % (body,)
  9.  
  10. #每遇到一个点,就sleep一秒钟,模拟长时间任务
  11. sleep_time = body.count('.')*100
  12. print "slepp_time=%d" % sleep_time
  13.  
  14. time.sleep(body.count('.')*100)
  15.  
  16. print " [x] Done"
  17.  
  18. #任务执行完成之后返回确认包
  19. #这样对于没有返回确认包的消息就不会丢失
  20. ch.basic_ack(delivery_tag= method.delivery_tag)
  21.  
  22. def work():
  23. connection = pika.BlockingConnection(pika.ConnectionParameters(
  24. host='localhost'))
  25. channel = connection.channel()
  26.  
  27. channel.queue_declare(queue='task_queue',durable=True)
  28.  
  29. print "[*] Wating for messages.To exit press CTRL+C"
  30.  
  31. #保证消息的公平分发,设置prefetch告诉同一时刻,不要发送超过1条消息给一个工作者
  32. #直到它已经处理上一条消息并且做出响应
  33. channel.basic_qos(prefetch_count=1)
  34.  
  35. #开始消费消息
  36. channel.basic_consume(callback,queue='task_queue')
  37.  
  38. #循环消费
  39. #channel.start_consuming()
  40.  
  41. if __name__ == '__main__':
  42. try:
  43. work()
  44. except KeyboardInterrupt,e:
  45. 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中消息堆积,占用越来越多的内存。通过如下命令进行确认:

  1. guosong@guosong:~/code/rabbitmq/ch2$ rabbitmqctl list_queues name messages_ready messages_unacknowledged
  2. Listing queues ...
  3. task_queue 3 0
  4. ...done.

存在三个堆积的任务

7、关于队列大小:如果所有的工作者都在处理任务,队列就会被填满。需要留意这个问题,要么添加更多的工作者,要么使用其他策略,例如设置队列大小等。

send和receive

  1. ChannelClosed: (406, "PRECONDITION_FAILED - parameters for queue 'rt_test_dba_queue' in vhost '/' not equivalent")
  2. (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之工作队列的更多相关文章

  1. 【译】RabbitMQ:工作队列(Work Queue)

    在第一篇我们写了两个程序通过一个命名的队列分别发送和接收消息.在这一篇,我们将创建一个工作队列在多个工作线程间分发耗时的工作任务. 工作队列的核心思想是避免立刻处理资源密集型任务导致必须等待其执行完成 ...

  2. RabbitMQ的工作队列和路由

    工作队列:Working Queue   工作队列这个概念与简单的发送/接收消息的区别就是:接收方接收到消息后,可能需要花费更长的时间来处理消息,这个过程就叫一个Work/Task.   几个概念 分 ...

  3. RabbitMQ 笔记-工作队列

    工作队列的主要思想是不用等待资源密集型的任务处理完成, 为了确保消息或者任务不会丢失,rabbitmq 支持消息确信 ACK.ACK机制是消费者端从rabbitmq收到消息并处理完成后,反馈给rabb ...

  4. RabbitMQ (四) 工作队列之公平分发

    上篇文章讲的轮询分发 : 1个队列,无论多少个消费者,无论消费者处理消息的耗时长短,大家消费的数量都一样. 而公平分发,又叫 : 能者多劳,顾名思义,处理得越快,消费得越多. 生产者 public c ...

  5. RabbitMQ (三) 工作队列之轮询分发

    上一篇讲了简单队列,实际工作中,这种队列应该很少用到,因为生产者发送消息的耗时一般都很短,但是消费者收到消息后,往往伴随着对高消息的业务逻辑处理,是个耗时的过程,这势必会导致大量的消息积压在一个消费者 ...

  6. RabbitMQ学习笔记(二) 工作队列

    什么是工作队列? 工作队列(又名任务队列)是RabbitMQ提供的一种消息分发机制.当一个Consumer实例正在进行资源密集任务的时候,后续的消息处理都需要等待这个实例完成正在执行的任务,这样就导致 ...

  7. RabbitMQ入门(二)工作队列

      在文章RabbitMQ入门(一)之Hello World,我们编写程序通过指定的队列来发送和接受消息.在本文中,我们将会创建工作队列(Work Queue),通过多个workers来分配耗时任务. ...

  8. .NET Core RabbitMQ探索(1)

    RabbitMQ可以被比作一个邮局,当你向邮局寄一封信时,邮局会保证将这封信送达你写的收件人,而RabbitMQ与邮局最主要的区别是,RabbitMQ并不真的处理信件,它处理的是二进制的数据块,它除了 ...

  9. 消息中间件-RabbitMQ基本使用

    RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件).RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的.所有主要 ...

随机推荐

  1. AVPlayer缓存实现

    没有任何工具能适用于所有的场景,在使用AVPlayer的过程中,我们会发现它有很多局限性,比如播放网络音乐时,往往不能控制其内部播放逻辑,比如我们会发现播放时seek会失败,数据加载完毕后不能获取到数 ...

  2. 【转载】jQuery全屏滚动插件fullPage.js

    文章转载自dowebok http://www.dowebok.com/ 原文链接:http://www.dowebok.com/77.html 简介 如今我们经常能见到全屏网站,尤其是国外网站.这些 ...

  3. python 解析xml

    在工作中很多时候都要用到xml,使用这个时候难免会设计到解析他,然后就研究了一下python解析xml问题,看了很多东西,python有很多解析xml的包,但是也折腾我好一段时间,最后选择了这个方法. ...

  4. win10 UWP 应用设置

    win10 UWP 应用设置 简单的把设置需要的,放到微软自带的LocalSettings LocalSettings.Values可以存放几乎所有数据 如果需要存放复合数据,一个设置项是由多个值组成 ...

  5. JavaWeb之Maven配置

    Maven和C#的nuget类似,可以通过设置就能引入框架等第三方,方便又省事.Java中使用Maven来管理第三方.今天尝试着配置了一下. 一.JDK的安装 关于JDK的安装可以查看百度经验,设置P ...

  6. 2017上海QCon之旅总结(上)

    本来这个公众号的交流消息中间件相关的技术的.这周去上海参加了QCon,第一次参加这样的技术会议,感受挺多的,所以整理一下自己的一些想法接公众号和大家交流一下. 下面进入正题,从自己参加了的一些分享中挑 ...

  7. 【转】DMA和cache一致性

    DMA和cache一致性问题 Cache原理 CPU缓存(Cache Memory)是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多.缓存的出现主要是为了解决CPU ...

  8. LINUX 笔记之常用打包压缩命令

    1.将所有.jpg文件打成一个名为all.tar的包 tar -cf all.tar *.gif 2.将所有.gif文件追加到all.tar tar -rf all.tar *.gif 3.更新原来t ...

  9. Ajax禁止重复提交

    var pendingRequests = []; var generatePendingRequestKey = function (obj) { return obj.data || {}; } ...

  10. LeetCode 289. Game of Life (生命游戏)

    According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...