python之RabbitMQ消息队列

RabbitMQ:消息队列

PY里的队列有:线程QUEUE、进程QUEUE

进程queue可以用于父进程与子进程进行交互,或者同属于一父进程下多个子进程进行交互,但如果是两个独立的程序,是不能用这个QUEUE进行通讯的

两个独立的程序之间,要找一个中间代理,比如可以用socket通讯,或者用json通讯(放在硬盘上,然后在读取,速度慢),还有就是RabbitMQ消息队列

这个中间代理的好处在于:

1、完全封装好,不用考虑消息的处理。

2、可以多个消息之间建立连接,而不必每两个程序就要建立socket连接。

中间代理代表是rabbitMQ。

RabbitMQ在python里的调用模块是pika

基本用法如下面:

生产者:

import pika

connection = pika.BlockingConnection(
    pika.ConnectionParameters('localhost')
)
channel = connection.channel()  #声明一个管道

#在管道里,再声明queue
channel.queue_declare(queue='hello',
                      # durable=True  #durable=True为队列持续化
                      )

#真正发消息,用管道发
channel.basic_publish(exchange='',
                      routing_key='hello',  #消息队列名称
                      body='Hello World!',  #消息内容
                      # properties=pika.BasicProperties(delivery_mode=2,) #消息持续化
)

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

消费者:

import pika

connection = pika.BlockingConnection(
    pika.ConnectionParameters('localhost')
)
channel = connection.channel()

#这里再次声明从那个队列去收消息(可以不写,但必须要有这个队列,不然会报错)
channel.queue_declare(queue='hello',
                      # durable=True  #durable=True为队列持续化
                      )

def callback(ch, method, properties, body):
    print('[x] 收到%r'%body)
    # 给队列发一个确认执行完的信息,否则消息会保存起来,不会被消费掉,会转给下个消费者
    ch.basic_ack(delivery_tag=method.delivery_tag)


channel.basic_qos(prefetch_count=1)

channel.basic_consume(
    callback,
    queue='hello',
    # no_ack=True   #取消发送消息中断处理功能,不管有没有处理完,都不会给服务器端发确认
)

print('[*] Waiting for messages. Toexit press CTRL+C')
channel.start_consuming()

生产消费者模型默认是轮询处理机制:如果有3个消费者,一个生产者,则是先给第一个启动的消费者,在给第二个……


回调函数(callback函数):表示消息来了就调这个函数。

有的时候发送消息,会中断,那么RabbitMQ会有处理机制:在回调函数最后加上ch.basic_ack(delivery_tag=method.delivery_tag),RabbitMQ在函数没处理完就中断的话,消息会保存起来,不会被消费掉,会转给下个消费者。取消这个功能代码是:no_ack=True,代表不管有没有处理完,都不会给服务器端发确认(在服务器端不关心消息有没有处理完的时候用)。

在sbin目录下ctl是管理队列的工具。命令行用rabbitmqctl.bat list_queues可以看到队列和他的消息有多少个。


如果服务器突然断开了,那么怎么办呢。在每次声明队列的时候,加上队列持续化durable=True。和消息持续化:


怎么样能够根据cpu处理速度调整发多少消息呢?

在消费者的basic_consume方法前面加上:


怎么吧一条消息发给所有人(广播)?

要用到exchange:

发布方:要定义exchange,类型是fanout。

channel.exchange_declare(exchange='logs', type='fanout')

完整代码如下

import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(
    host='localhost'))
channel = connection.channel()

channel.exchange_declare(exchange='logs', type='fanout')

message = "info: Hello World!"
channel.basic_publish(exchange='logs',
                      routing_key='',
                      body=message)
print(" [x] Sent %r" % message)
connection.close()

接受方:直接看完整代码

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
    host='localhost'))
channel = connection.channel()

#这里是一样的定义exchange
channel.exchange_declare(exchange='logs',
                         type='fanout')

#消费者还是要有一个queue,这里声明一个随机queue
# 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue    #拿到queue

#然后要bind一个exchange,后面就可以开始收了
channel.queue_bind(exchange='logs',
                   queue=queue_name)

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


def callback(ch, method, properties, body):
    print(" [x] %r" % body)


channel.basic_consume(callback,
                      queue=queue_name,
                      no_ack=True)

channel.start_consuming()

 


如果想要选择性的接收:接收方的type换成direct就行

 

Rpc:发一条消息到远程机器去执行,然后吧执行结果返回,这种模式叫rpc(remote procedure call)

猜你喜欢

转载自blog.csdn.net/likunkun__/article/details/83112688