1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. @author: zengchunyun
  5. """
  6. import pika
  7.  
  8. class MQServer(object):
  9. def __init__(self, host, port=5672, exchange=None, exchange_type="topic"):
  10. """
  11. 初始化MQ设置
  12. :param host: MQ服务器地址
  13. :param port: MQ端口
  14. :param exchange: 交换器名称
  15. :param exchange_type: 交换器类型,默认关键字类型
  16. :return:
  17. """
  18. self.host = host
  19. self.port = port
  20. self.exchange = exchange
  21. self.exchange_type = exchange_type
  22. self.queue = None
  23. self.connection = self.connect()
  24. self.channel = self.connect_channel()
  25. self.create_exchange()
  26.  
  27. def connect(self):
  28. """
  29. 连接MQ服务器
  30. :return:
  31. """
  32. return pika.BlockingConnection(pika.ConnectionParameters(host=self.host, port=self.port))
  33.  
  34. def connect_channel(self):
  35. """
  36. 创建频道
  37. :return:
  38. """
  39. return self.connection.channel()
  40.  
  41. def create_exchange(self):
  42. """
  43. 定义交换器名称,防止发布时,如果交换器不存在,异常
  44. :return:
  45. """
  46. self.channel.exchange_declare(exchange=self.exchange, type=self.exchange_type)
  47.  
  48. def publish(self, exchange=None, routing_key=None, body=None):
  49. """
  50. 创建发布者
  51. :param exchange: 交换器名称
  52. :param routing_key: 路由KEY
  53. :param body:消息主体
  54. :return:
  55. """
  56. if exchange:
  57. self.exchange = exchange
  58. self.channel.basic_publish(exchange=self.exchange, routing_key=routing_key, body=body)
  59. self.close()
  60.  
  61. def consumer(self, exchange=None, routing_key=None, callback=None):
  62. """
  63. 创建消费者
  64. :param exchange:
  65. :param routing_key:
  66. :param callback:
  67. :return:
  68. """
  69. if exchange:
  70. self.exchange = exchange
  71. self.create_queue()
  72. self.channel.queue_bind(queue=self.queue, exchange=self.exchange, routing_key=routing_key)
  73. self.channel.basic_consume(consumer_callback=callback, queue=self.queue, no_ack=True)
  74. self.start()
  75.  
  76. def create_queue(self):
  77. """
  78. 生成队列,当关闭consumer时,加上exclusive=True,queue也会被删除
  79. :return:
  80. """
  81. self.queue = self.channel.queue_declare(exclusive=True).method.queue # 为每个消费者生成不同的队列
  82.  
  83. def close(self):
  84. """
  85. 关闭消息连接
  86. :return:
  87. """
  88. self.connection.close()
  89.  
  90. def start(self):
  91. self.channel.start_consuming()

1.消息持久化存储

  虽然有了消息反馈机制,但如果rabbitmq自身挂掉的话,那么任务还是会丢失,所以需要将任务持久化存储起来,

durable=True  # 开启持久化设置,rabbitmq不允许使用不同的参数来重新定义存在的队列

  1. self.queue = self.channel.queue_declare(exclusive=True,durable=True)
  1. self.channel.exchange_declare(exchange=self.exchange, type=self.exchange_type, durable=True)
    在发送任务的时候,用delivery_mode2来标记任务为持久化存储
  1. self.channel.basic_publish(exchange='',
  2. routing_key=routing_key,
  3. body=message,
  4. properties=pika.BasicProperties(
  5. delivery_mode = 2, # make message persistent
  6. ))

2.公平调度(fair dispatch)

虽然每个工作者是依次分配到任务,但是每个任务不一定一样,可能有到任务比较重,执行时间长,有的任务比较轻,执行时间短,如果能公平调度最好了,使用basic_qos设置prefetch_count=1,使得rabbitmq不会在同一时间给工作者分配多个任务,即只有工作者完成任务之后,才会再次接收到任务

  1. channel.basic_qos(prefetch_count=1)

完整示例代码

  1. #!/usr/bin/env python
  2. import pika
  3. import sys
  4.  
  5. connection = pika.BlockingConnection(pika.ConnectionParameters(
  6. host='localhost'))
  7. channel = connection.channel()
  8.  
  9. channel.queue_declare(queue='task_queue', durable=True)
  10.  
  11. message = ' '.join(sys.argv[1:]) or "Hello World!"
  12. channel.basic_publish(exchange='',
  13. routing_key='task_queue',
  14. body=message,
  15. properties=pika.BasicProperties(
  16. delivery_mode = 2, # make message persistent
  17. ))
  18. print (" [x] Sent %r" % (message,))
  19. connection.close()

消费者代码

  1. #!/usr/bin/env python
  2. import pika
  3. import time
  4.  
  5. connection = pika.BlockingConnection(pika.ConnectionParameters(
  6. host='localhost'))
  7. channel = connection.channel()
  8.  
  9. channel.queue_declare(queue='task_queue', durable=True)
  10. print( ' [*] Waiting for messages. To exit press CTRL+C')
  11.  
  12. def callback(ch, method, properties, body):
  13. print (" [x] Received %r" % (body,))
  14. time.sleep( body.count('.') )
  15. print (" [x] Done")
  16. ch.basic_ack(delivery_tag = method.delivery_tag)
  17.  
  18. channel.basic_qos(prefetch_count=1)
  19. channel.basic_consume(callback,
  20. queue='task_queue')
  21.  
  22. channel.start_consuming()
  1.  

rabbitmq应用的更多相关文章

  1. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  2. RabbitMq应用二

    在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,rabbitmq内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...

  3. 如何优雅的使用RabbitMQ

    RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具.消息队列的使用场景大概有3种: 1.系统集成,分布式系统的设 ...

  4. RabbitMq应用一的补充(RabbitMQ的应用场景)

    直接进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完 ...

  5. RabbitMq应用一

    RabbitMq应用一 RabbitMQ的具体概念,百度百科一下,我这里说一下我的理解,如果有少或者不对的地方,欢迎纠正和补充. 一个项目架构,小的时候,一般都是传统的单一网站系统,或者项目,三层架构 ...

  6. 缓存、队列(Memcached、redis、RabbitMQ)

    本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...

  7. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  8. windows下 安装 rabbitMQ 及操作常用命令

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rab ...

  9. RabbitMQ + PHP (三)案例演示

    今天用一个简单的案例来实现 RabbitMQ + PHP 这个消息队列的运行机制. 主要分为两个部分: 第一:发送者(publisher) 第二:消费者(consumer) (一)生产者 (创建一个r ...

  10. RabbitMQ + PHP (二)AMQP拓展安装

    上篇说到了 RabbitMQ 的安装. 这次要在讲案例之前,需要安装PHP的AMQP扩展.不然可能会报以下两个错误. 1.Fatal error: Class 'AMQPConnection' not ...

随机推荐

  1. Mybatis-PageHelper

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  2. solr面板的使用

    创建数据库 先别着急点击Add Core,先去目录下创建几个文件. 去solrhome目录下创建一个文件夹,比如test,这个文件夹就是数据库文件夹.

  3. RT-SA-2019-004 Cisco RV320 Unauthenticated Diagnostic DataRetrieval

    Advisory: Cisco RV320 Unauthenticated Diagnostic Data Retrieval RedTeam Pentesting discovered that t ...

  4. JavaSE笔记-注释

    Annotation Annotation是一个接口,可以把Annotation当成一个修饰符 Annotation的定义 注解通过@interface定义 public @interface Tes ...

  5. gcc 8.2.1 / MCF thread 简介

    gcc 8.2.1 下载 地址 https://gcc-mcf.lhmouse.com/ MCF threadhttps://github.lhmouse.com/ MCF thread 简介MCF ...

  6. Java并发编程的4个同步辅助类

    Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...

  7. sqlite 中的分页语句

    2个关键字 select * from testtable limit 2 offset 1;

  8. linux 乌班图 nginx php直接下载下来

    location ~ \.php(.*)$ { include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets ...

  9. SpringBoot webmvc项目导出war包并在外部tomcat运行产生的诸多问题以及解决方案

    背景: 有需求要将原来的Spring(3.2.6) + Springmvc + Hibernate项目重构为Springboot(1.5.2)项目 描述: 记录重构过程,以及期间遇到的种种问题和对应的 ...

  10. jade模板 注意事项

    1.   jade模板 语法 doctype html html head body header div 2.  添加内容:直接在标签后边加空格 直接写内容 如下: div  我要写的内容 3.  ...