python中通过pika,应用RabbitMQ,有多种形式:

一、简单队列模型

简单队列模型:交换机此处不工作(exchange=‘’),只针对唯一指定的队列进行操作的生产者、消费者模型,

使用queue实现:基于内存中的一个queue对象

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import Queue
import threading


message = Queue.Queue(10)


def producer(i):
    while True:
        message.put(i)


def consumer(i):
    while True:
        msg = message.get()


for i in range(12):
    t = threading.Thread(target=producer, args=(i,))
    t.start()

for i in range(10):
    t = threading.Thread(target=consumer, args=(i,))
    t.start()
基于queue的生产者、消费者模型

使用RabbitMQ实现:基于另一台服务器的RabbitMQ Server

(一)实现流程

此处,无论是生产者还是消费者:

  首先,都需要与RabbitMQ Server建立socket连接,并获得操作句柄

  然后,通过操作句柄查找或者创建指定队列

有了指定队列,才能开始添加或读取信息的操作:

  生产者:向队列中添加数据、之后关闭连接

  消费者:开始等待队列中的数据信息,从队列中读取数据、数据通过参数传入回调函数、回调函数自执行,数据是否立即删除由参数no_ack指定,

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 简单队列模型:交换机不工作,只针对唯一指定的队列进行操作,

# -----------------------生产者--------------------------------

# 0、导入RabbitMQ在Python中的接口pika,
import pika

# 1、封装socket逻辑部分,由host指定访问的RabbitMQ Server,
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))

# 2、获得操作句柄,通过此句柄对RabbitMQ进行操作,
channel = connection.channel()

# 3、检查队列是否已存在,不存在时创建并命名,消费者取数据时需通过名字找到相应队列,
channel.queue_declare(queue='hello',durable=True)

# 4、向队列中添加数据,注意三个参数,
channel.basic_publish(exchange='',              # 交换机,此处不工作,
                      routing_key='hello',      # 队列名称,
                      body='Hello World!',     # 添加的数据,
                      properties=pika.BasicProperties(delivery_mode=2),   # make message properties数据持久性
                      )

# 操作提示信息,非必需
print(" [x] Sent 'Hello World!'")

# 5、添加数据完毕,关闭socket连接
connection.close()
生产者
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 简单队列模型:交换机不工作,只针对唯一指定的队列进行操作,

# ---------------------消费者---------------------

# 0、导入RabbitMQ在Python中的接口pika,
import pika

# 1、封装socket逻辑部分,由host指定访问的RabbitMQ Server,
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))

# 2、获得操作句柄,通过此句柄对RabbitMQ进行操作,
channel = connection.channel()

# 3、检查队列是否已存在,不存在时创建并命名,避免消费者先于生产者启动时报错,
channel.queue_declare(queue='hello')


# 5、从指定队列中取数据,以参数body方式传入回调函数,并自执行回调函数,
# def callback(ch, method, properties, body):
#     print(" [x] Received %r" % body)
#
# channel.basic_consume(callback,
#                       queue='hello',
#                       no_ack=True)
# no_ack:True表示队列中的数据取过就直接删除,无论执行结果如何,效率高,
# no_ack:False表示队列中数据取过后不直接删除,执行成功后才删除,安全性高,
def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)
    ch.basic_ack(delivery_tag=method.delivery_tag)   # no_ack=False时,需要在回调函数中添加这句代码

channel.basic_qos(prefetch_count=1)  # 数据谁来谁取,不按奇偶数顺序

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=False)

print(' [*] Waiting for messages. To exit press CTRL+C')

# 4、开始等待队列中的数据到来,
channel.start_consuming()
消费者

(二)重点参数

 1、数据不丢失(消费者no_ack)

  no_ack=True:队列中的数据取过后直接删除,无论回调函数的执行结果如何,效率高,

  no_ack=False:队列中数据取过后不直接删除,回调函数执行成功后才删除,安全性高,

  注意:当no_ack=False时,需要在回调函数中添加一句代码:ch.basic_ack(delivery_tag=method.delivery_tag)

     

 2、数据不丢失(生产者durable)

  durable=True:将数据写入硬盘,支持数据的持久性,同时需要设置properties.delivery_mode=2,

  durable=Flase:为默认值,将数值保留在内存,若出现掉线或异常,数据可能丢失,

    

 3、消息获取顺序(消费者)

   默认是多个消费者按照自然顺序排队获取消息,通过如下设置,可以控制谁来谁取,避免个别消费者太慢影响进程,

    

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 简单队列模型:交换机不工作,只针对唯一指定的队列进行操作,

# -----------------------生产者--------------------------------
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# 声明队列
channel.queue_declare(queue='hello',durable=True)

# 向队列中添加数据
channel.basic_publish(exchange='',              # 交换机,此处不工作,
                      routing_key='hello',      # 队列名称,
                      body='Hello World!',     # 添加的数据,
                      properties=pika.BasicProperties(delivery_mode=2),   # make message properties数据持久性
                      )

print(" [x] Sent 'Hello World!'")
connection.close()

# ---------------------消费者---------------------
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# 声明队列
channel.queue_declare(queue='hello')

# 从队列中取数据并执行回调函数
def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)
    ch.basic_ack(delivery_tag=method.delivery_tag)   # no_ack=False时,需要在回调函数中添加这句代码

channel.basic_qos(prefetch_count=1)  # 数据谁来谁取,不按奇偶数顺序

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=False,)

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
简单队列模型代码