• python操作RabbiMQ


    RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。

    MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

    puthon操作rabbitMQ的模块名为:pika
     
     
    在操作rabbitMQ之前,先通过Queue理解生产者消费者模型
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import  Queue
     5 import  threading
     6 
     7 message = Queue.Queue(10)
     8 
     9 
    10 def producter(i):
    11 
    12     while True:
    13         message.put(i)
    14 
    15 def consumer(i):
    16     while True:
    17         message.get()
    18 
    19 
    20 
    21 for i in range(5):
    22     w = threading.Thread(target=producter,args=(i,))
    23     w.start()
    24 
    25 for i in range(2):
    26     w = threading.Thread(target=consumer,args=(i,))
    27     w.start()
    生产者消费者模型

    对于RabbitMQ来说,生产和消费不再针对内存里的一个Queue对象,而是某台服务器上的RabbitMQ Server实现的消息队列。

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import  pika
     5 
     6 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.108')) #连接一台rabbitMQ
     7 
     8 channel = connection.channel()  #创建一个频道
     9 
    10 channel.queue_declare("chenchao")  #声明一个消息队列
    11 
    12 
    13 channel.basic_publish(exchange='',routing_key="chenchao",body="Fucking!")   #发送消息
    14 
    15 print "sent Fucking world!!!!"
    16 
    17 connection.close()  #关闭连接
    生产者
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 # #############################消费者########################
     5 
     6 import  pika
     7 
     8 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.108'))
     9 
    10 channel = connection.channel()
    11 
    12 channel.queue_declare("chenchao")
    13 
    14 def callback(ch, method, properties, body):  #固定格式 必须有4个参数
    15     print body
    16 
    17 
    18 channel.basic_consume(callback,queue="chenchao",no_ack=True)  #将从队列里取出的数据回调给callback方法
    19 
    20 channel.start_consuming()   #开始取值
    消费者

     1、acknowledgment 消息不丢失

    no-ack = False,如果在传递消息的过程中消费者遇到情况(its channel is closed, connection is closed, or TCP connection is lost)挂掉了,那么,RabbitMQ会重新将该任务消息添加到队列中。

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 # #############################消费者########################
     5 
     6 import  pika
     7 
     8 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.108'))
     9 
    10 channel = connection.channel()
    11 
    12 channel.queue_declare("chenchao")
    13 
    14 def callback(ch, method, properties, body):  #固定格式 必须有4个参数
    15     print body
    16     import time
    17     time.sleep(8)
    18     print "sleep over"
    19     ch.basic_ack(delivery_tag = method.delivery_tag )   #向生产者发送应答
    20 
    21 
    22 channel.basic_consume(callback,queue="chenchao",no_ack=False)  #将从队列里取出的数据回调给callback方法
    23 
    24 channel.start_consuming()   #开始取值
    消费者
    ch.basic_ack(delivery_tag = method.delivery_tag )   #向生产者发送应答,表示已经接收到了数据
    no_ack=False

    2、durable   消息不丢失

    如果之前的队列为非持久化的,那么之后就不能将其修改为持久化的,必须重新创建一个新的队列,并声明为持久化的队列,并且在发送消息时也要注明是持久化消息才行。

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 # #######################生产者######################
     5 
     6 import  pika
     7 
     8 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.108')) #连接一台rabbitMQ
     9 
    10 channel = connection.channel()  #创建一个频道
    11 
    12 channel.queue_declare("chenchao2",durable=True)  #声明一个消息队列为持久化的队列
    13 
    14 
    15 channel.basic_publish(exchange='',
    16                       routing_key="chenchao2",
    17                       body="Message NO.1",
    18                       properties=pika.BasicProperties(delivery_mode=2,))  #发送消息为持久化的数据
    19 
    20 print "sent Message OK!"
    21 
    22 connection.close()  #关闭连接
    生产者
    durable=True
    properties=pika.BasicProperties(delivery_mode=2,)
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 # #############################消费者########################
     5 
     6 import  pika
     7 
     8 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.108'))
     9 
    10 channel = connection.channel()
    11 
    12 channel.queue_declare("chenchao2",durable=True)  #生命一个可持续化的队列(如果队列已经存在,这句可有可无)
    13 
    14 def callback(ch, method, properties, body):  #固定格式 必须有4个参数
    15     print body
    16     import time
    17     time.sleep(8)
    18     print "sleep over"
    19     ch.basic_ack(delivery_tag = method.delivery_tag )   #向生产者发送应答
    20 
    21 
    22 channel.basic_consume(callback,queue="chenchao2",no_ack=False)  #将从队列里取出的数据回调给callback方法
    23 
    24 channel.start_consuming()   #开始取值
    消费者

    3、消息获取顺序

    默认消息队列里的数据是按照顺序被消费者拿走,例如:消费者1 去队列中获取 奇数 序列的任务,消费者1去队列中获取 偶数 序列的任务。

    channel.basic_qos(prefetch_count=1) 表示谁来谁取,不再按照奇偶数排列

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 # #############################消费者########################
     5 
     6 import  pika
     7 
     8 connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.1.108'))
     9 
    10 channel = connection.channel()
    11 
    12 channel.queue_declare("chenchao2",durable=True)  #生命一个可持续化的队列(如果队列已经存在,这句可有可无)
    13 
    14 def callback(ch, method, properties, body):  #固定格式 必须有4个参数
    15     print body
    16     import time
    17     time.sleep(8)
    18     print "sleep over"
    19     ch.basic_ack(delivery_tag = method.delivery_tag )   #向生产者发送应答
    20 
    21 channel.basic_qos(prefetch_count=1)   #获取消息不在按奇偶规则获取
    22 
    23 channel.basic_consume(callback,queue="chenchao2",no_ack=False)  #将从队列里取出的数据回调给callback方法
    24 
    25 channel.start_consuming()   #开始取值
    消费者

    4、发布订阅

    发布订阅和简单的消息队列区别在于,发布订阅会将消息发送给所有的订阅者,而消息队列中的数据被消费一次便消失。所以,RabbitMQ实现发布和订阅时,会为每一个订阅者创建一个队列,而发布者发布消息时,会将消息放置在所有相关队列中。

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 import sys
     6 
     7 connection = pika.BlockingConnection(pika.ConnectionParameters(
     8         host='192.168.1.108'))
     9 channel = connection.channel()
    10 
    11 
    12 channel.exchange_declare(exchange='chenchao',
    13                          type='fanout')     #声明一个名称为chenchao的exchange  类型为fanout
    14 
    15 
    16 message = ' '.join(sys.argv[1:]) or "info: Hello every consumer2"
    17 channel.basic_publish(exchange='chenchao',
    18                       routing_key='',
    19                       body=message)      #将消息发送到exchange里,通过exchange发送到所有队列
    20 print(" [x] Sent %r" % message)
    21 connection.close()
    发布者
    channel.exchange_declare(exchange='chenchao',
    type='fanout') #声明一个名称为chenchao的exchange 类型为fanout

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 
     6 connection = pika.BlockingConnection(pika.ConnectionParameters(
     7         host='192.168.1.108'))
     8 channel = connection.channel()
     9 
    10 
    11 channel.exchange_declare(exchange='chenchao',
    12                          type='fanout')       #声明类型为fanou名称为chenchao的exchange
    13 
    14 result = channel.queue_declare(exclusive=True)
    15 queue_name = result.method.queue     #生成一个随机名的队列
    16 
    17 channel.queue_bind(exchange='chenchao',
    18                    queue=queue_name)    #将队列与exchange绑定
    19 
    20 print(' [*] Waiting for logs. To exit press CTRL+C')
    21 
    22 def callback(ch, method, properties, body):
    23     print(" [x] %r" % body)
    24 
    25 channel.basic_consume(callback,
    26                       queue=queue_name,
    27                       no_ack=True)
    28 
    29 channel.start_consuming()
    订阅者
    channel.queue_bind(exchange='chenchao',
    queue=queue_name) #将队列与exchange绑定



    5、关键字发送

     exchange type = direct

    之前事例,发送消息时明确指定某个队列并向其中发送消息,RabbitMQ还支持根据关键字发送,即:队列绑定关键字,发送者将数据根据关键字发送到消息exchange,exchange根据 关键字 判定应该将数据发送至指定队列。

     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 import sys
     6 
     7 connection = pika.BlockingConnection(pika.ConnectionParameters(
     8         host='192.168.1.108'))
     9 channel = connection.channel()
    10 
    11 
    12 channel.exchange_declare(exchange='import',
    13                          type='direct')     #声明一个名称为import的exchange  类型为direct
    14 
    15 
    16 message = ' '.join(sys.argv[1:]) or "info: Hello are you Q1???"
    17 channel.basic_publish(exchange='import',
    18                       routing_key='Nice',
    19                       body=message)      #将消息与关键字发送到exchange里,通过关键字发送到绑定的队列
    20 print(" [x] Sent %r" % message)
    21 connection.close()
    生产者
    type='direct'
    routing_key='Nice'
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 
     6 connection = pika.BlockingConnection(pika.ConnectionParameters(
     7         host='192.168.1.108'))
     8 channel = connection.channel()
     9 
    10 
    11 channel.exchange_declare(exchange='import',
    12                          type='direct')       #声明类型为direct名称为import的exchange
    13 
    14 result = channel.queue_declare(exclusive=True)
    15 queue_name = result.method.queue     #生成一个随机名的队列
    16 
    17 channel.queue_bind(exchange='import',
    18                    queue=queue_name,
    19                    routing_key="Queue1")    #将队列与exchange绑定,并声明关键字
    20 
    21 
    22 channel.queue_bind(exchange='import',
    23                    queue=queue_name,
    24                    routing_key="Nice")    #将队列与exchange绑定,并声明关键字
    25 
    26 print(' [*] Waiting for logs. To exit press CTRL+C')
    27 
    28 def callback(ch, method, properties, body):
    29     print(" [x] %r:%r" % (method.routing_key, body))
    30 
    31 channel.basic_consume(callback,
    32                       queue=queue_name,
    33                       no_ack=True)
    34 
    35 channel.start_consuming()
    订阅者
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 
     6 connection = pika.BlockingConnection(pika.ConnectionParameters(
     7         host='192.168.1.108'))
     8 channel = connection.channel()
     9 
    10 
    11 channel.exchange_declare(exchange='import',
    12                          type='direct')       #声明类型为direct名称为import的exchange
    13 
    14 result = channel.queue_declare(exclusive=True)
    15 queue_name = result.method.queue     #生成一个随机名的队列
    16 
    17 channel.queue_bind(exchange='import',
    18                    queue=queue_name,
    19                    routing_key="Queue2")    #将队列与exchange绑定,并声明关键字
    20 
    21 
    22 channel.queue_bind(exchange='import',
    23                    queue=queue_name,
    24                    routing_key="Nice")    #将队列与exchange绑定,并声明关键字
    25 
    26 print(' [*] Waiting for logs. To exit press CTRL+C')
    27 
    28 def callback(ch, method, properties, body):
    29     print(" [x] %r:%r" % (method.routing_key, body))
    30 
    31 channel.basic_consume(callback,
    32                       queue=queue_name,
    33                       no_ack=True)
    34 
    35 channel.start_consuming()
    订阅者2

      type='direct'

      routing_key="Nice"

    6、模糊匹配

     exchange type = topic

    在topic类型下,可以让队列绑定几个模糊的关键字,之后发送者将数据发送到exchange,exchange将传入”路由值“和 ”关键字“进行匹配,匹配成功,则将数据发送到指定队列。

    • # 表示可以匹配 0 个 或 多个 单词
    • *  表示只能匹配 一个 单词
    routing_key="Nice.*"
    routing_key="Nice.#"

    发送者路由值              队列中
    old.boy.python          old.*  -- 不匹配
    
    
    old.boy.python          old.#  -- 匹配
     
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 import sys
     6 
     7 connection = pika.BlockingConnection(pika.ConnectionParameters(
     8         host='192.168.1.108'))
     9 channel = connection.channel()
    10 
    11 
    12 channel.exchange_declare(exchange='topic_logs',
    13                          type='topic')     #声明一个名称为import的exchange  类型为direct
    14 
    15 
    16 message = ' '.join(sys.argv[1:]) or "info: Are you choosed?"
    17 channel.basic_publish(exchange='topic_logs',
    18                       routing_key='Nice',
    19                       body=message)      #将消息与关键字发送到exchange里,通过关键字发送到绑定的队列
    20 print(" [x] Sent %r" % message)
    21 connection.close()
    发布者
    type='topic'
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 
     6 connection = pika.BlockingConnection(pika.ConnectionParameters(
     7         host='192.168.1.108'))
     8 channel = connection.channel()
     9 
    10 
    11 channel.exchange_declare(exchange='topic_logs',
    12                          type='topic')       #声明类型为topic的exchange
    13 
    14 result = channel.queue_declare(exclusive=True)
    15 queue_name = result.method.queue     #生成一个随机名的队列
    16 
    17 
    18 channel.queue_bind(exchange='topic_logs',
    19                    queue=queue_name,
    20                    routing_key="Nice.*")    #将队列与exchange绑定,并声明关键字 *代表只能匹配一个
    21 
    22 print(' [*] Waiting for logs. To exit press CTRL+C')
    23 
    24 def callback(ch, method, properties, body):
    25     print(" [x] %r:%r" % (method.routing_key, body))
    26 
    27 channel.basic_consume(callback,
    28                       queue=queue_name,
    29                       no_ack=True)
    30 
    31 channel.start_consuming()
    订阅者1
    type='topic'
    routing_key="Nice.*"
     1 #!/usr/bin/env python
     2 # _*_coding:utf-8 _*_
     3 
     4 import pika
     5 
     6 connection = pika.BlockingConnection(pika.ConnectionParameters(
     7         host='192.168.1.108'))
     8 channel = connection.channel()
     9 
    10 
    11 channel.exchange_declare(exchange='topic_logs',
    12                          type='topic')       #声明类型为direct名称为import的exchange
    13 
    14 result = channel.queue_declare(exclusive=True)
    15 queue_name = result.method.queue     #生成一个随机名的队列
    16 
    17 channel.queue_bind(exchange='topic_logs',
    18                    queue=queue_name,
    19                    routing_key="Nice.#")    #将队列与exchange绑定,并声明关键字 #代表只能匹配0个或者多个
    20 
    21 print(' [*] Waiting for logs. To exit press CTRL+C')
    22 
    23 def callback(ch, method, properties, body):
    24     print(" [x] %r:%r" % (method.routing_key, body))
    25 
    26 channel.basic_consume(callback,
    27                       queue=queue_name,
    28                       no_ack=True)
    29 
    30 channel.start_consuming()
    订阅者2
    routing_key="Nice.#"
     

     

  • 相关阅读:
    delphi datetimepicker 修改时间无效问题
    C#写入文件
    C# winform中listview排序
    C/C++,python,java,C#月经贴问题
    Redis Sentinel 原理简单介绍
    JVM垃圾收集 知识汇总
    Java HotSpot VM Options
    Spring三级缓存解决循环依赖
    Markdown基础用法
    join示例分析
  • 原文地址:https://www.cnblogs.com/chenchao1990/p/5152484.html
Copyright © 2020-2023  润新知