RabbitMQ 消息队列

背景:python的Queue消息队列,只能python自己用。

--线程threading Queue 只能在一个进程间交互数据

--进程Queue最多可以父进程和多个子进程进行交互

常见队列工具:RabbitMQ、ZeroMQ、ActiveMQ

RabbitMQ 使用erlang语言开发的。

Python中和RibbitMQ交互的工具有pika、celery、Haigha

#!/usr/bin/env python
# Author:Zhangmingda

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel() #声明一个管道
channel.queue_declare(queue='hello',durable=True) #声明queue,持久化存储消息队列:durable=True
'''消息持久化:rabbitmq服务器在重启时不会丢失队列消息'''
channel.basic_publish( #向队列里面推送消息
    exchange='',
    routing_key='hello',
    body='hello World!',
    properties=pika.BasicProperties(delivery_mode=2,) #队列中的消息持久化,
)
connection.close() #关闭socket
pika-make-producer
#!/usr/bin/env python
# Author:Zhangmingda
import pika,time

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello',durable=True)

#不知道服务端还是客户端会先启动,接收端也声明队列名

def callback(ch,method,properties,body): #回调函数,在接收到消息后用来处理消息内容:body
    print('ch:',ch)
    print('method',method)
    print('properties',properties)
    print('body',body)
    print('sleep....')
    time.sleep(10)
    ch.basic_ack(delivery_tag=method.delivery_tag) #向rabbitmq发送任务已经执行结束的消息,然后rabbitmq删除队列中这个消息
    print('callback is over!')
channel.basic_qos(prefetch_count=3) #消息排队数量 根据处理器能力而定
channel.basic_consume(callback,
                 queue='hello')#)
                 # no_ack=True) #如果设置了no_ack (自动回复确认消息给rabbitmq,那么rabbitmq就不会保留消息队列,不论回调函数是否执行完成。)
                              #一般都不设置这个东西,就需要人为指定在哪里给rabbitmq设置删除队列消息的指令,保证只要没有收到消费端处理的结果就再rabbitmq中保留这个消息。然后交给下一个消费者继续重新做这个任务

print('一直等消息,么有了就卡住,to exit press CTRL+C')
channel.start_consuming()
pika-receive-consumer(从rabbitmq取消息)

同时向多个客户端发消息(广播)

#!/usr/bin/env python
# Author:Zhangmingda

import pika,sys

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel() #声明一个管道
# channel.queue_declare(queue='hello',durable=True) #声明queue,持久化存储消息队列:durable=True
'''广播发起时无需指定队列名字,统一由exchange分发'''

'''exchange 转发器进行广播,无需声明消息队列名,消息发过之后就没了'''
channel.exchange_declare(exchange='logs',exchange_type='fanout')
message = ' '.join(sys.argv[1:]) or 'info:Hello World!'
channel.basic_publish( #向队列里面推送消息
    exchange='logs', #向转发器发消息
    routing_key='', #无队列名,但是要置空
    body=message, #发送的消息内容
    properties=pika.BasicProperties(delivery_mode=2,) #队列中的消息持久化,
)
print('send message :',message)
connection.close() #关闭socket
#!/usr/bin/env python
# Author:Zhangmingda
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
# channel.queue_declare(queue='hello',durable=True)接收消息不直接通过队列,而是通过下面绑定到exchange上的临时队列来接收
channel.exchange_declare(exchange='logs',exchange_type='fanout') #声明要从哪个转发器接收广播
result = channel.queue_declare(exclusive=True)#获取消息队列实例。不指定queue名字,rabbit会随机分配一个名字,exclusive=True指的是使用此queue的消费者断开后,自动删除这个queue
queue_name = result.method.queue #从消息队列实例取消息队列名字
channel.queue_bind(exchange='logs',queue=queue_name) #将消息queue名字和转发器exchange绑定
'''接收广播消息,就像收音机,服务器那边发过之后不会保留消息,发当时没接收,就接收不到了'''
def callback(ch,method,properties,body): #回调函数,在接收到消息后用来处理消息内容:body
    print('ch:',ch)
    print('method',method)
    print('properties',properties)
    print('body',body)
    ch.basic_ack(delivery_tag=method.delivery_tag) #向rabbitmq发送任务已经执行结束的消息,然后rabbitmq删除队列中这个消息
    print('callback is over!')
channel.basic_qos(prefetch_count=1) #消息排队数量
channel.basic_consume(callback,
                 queue=queue_name)#从获取queue的临时的queue_name读任务
                 # no_ack=True) #如果设置了no_ack (自动回复确认消息给rabbitmq,那么rabbitmq就不会保留消息队列,不论回调函数是否执行完成。)
                              #一般都不设置这个东西,就需要人为指定在哪里给rabbitmq设置删除队列消息的指令,保证只要没有收到消费端处理的结果就再rabbitmq中保留这个消息。然后交给下一个消费者继续重新做这个任务

print('一直等消息,么有了就卡住,to exit press CTRL+C')
channel.start_consuming()
收消息端subscribe(订阅者)

猜你喜欢

转载自www.cnblogs.com/zhangmingda/p/9461407.html