背景: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
#!/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()
同时向多个客户端发消息(广播)
#!/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()