Python实现RabbitMQ的各种用法

以python语言为例演示rabbitmq的常用功能。

生产者发送消息:

1、fanout扇出模式(向某个交换器发送消息,绑定了该交换器的queue都会收到相同的消息)

def fanout_way():
    EXCHANGE = 'ali_callback_exchange'

    # 生成socket
    conn_params = pika.URLParameters('amqp://admin:admin@localhost:5672/%2F')
    connection = pika.BlockingConnection(conn_params)
    # 生成管道
    channel = connection.channel()
    ali_queue = channel.queue_declare(queue='ali_callback_queue', exclusive=False, auto_delete=False)
    huawei_queue = channel.queue_declare(queue='huawei_callback_queue', exclusive=False, auto_delete=False)
    # 声明交换器
    declared_exchange = channel.exchange_declare(exchange=EXCHANGE, exchange_type='fanout')
    # 绑定交换器
    channel.queue_bind('ali_callback_queue', EXCHANGE)
    channel.queue_bind('huawei_callback_queue', EXCHANGE)
    for i in range(10, 20):
        print(i)
        channel.basic_publish(exchange=EXCHANGE,
                              routing_key='', # 不需要指定key,指定也无效,交换器会自动把消息发送到绑定的队列中
                              body=json.dumps({"name": i}).encode(encoding='utf-8'),
                              properties=pika.BasicProperties(message_id=uuid.uuid4().__str__())
                              )
    connection.close()

2、direct直连模式(直接向某个queue发消息)

def direct_way():
    EXCHANGE = 'ali_callback_exchange'

    # 生成socket
    conn_params = pika.URLParameters('amqp://admin:admin@localhost:5672/%2F')
    connection = pika.BlockingConnection(conn_params)
    # 生成管道
    channel = connection.channel()
    ali_queue = channel.queue_declare(queue='ali_callback_queue', exclusive=False, auto_delete=False)
    # 声明交换器
    declared_exchange = channel.exchange_declare(exchange=EXCHANGE, exchange_type='fanout')
    for i in range(10, 20):
        print(i)
        channel.basic_publish(exchange='',
                              routing_key='ali_callback_queue', 
                              body=json.dumps({"name": i}).encode(encoding='utf-8'),
                              properties=pika.BasicProperties(message_id=uuid.uuid4().__str__())
                              )
    connection.close()

消费者消费消息:

QUEUE = 'huawei_callback_queue'
EXCHANGE = 'huawei_callback_exchange'

def on_message_callback(channel, method, props, body):
    content = json.loads(body.decode(encoding='utf-8'))
    print(content)
    # ack确认机制,告诉mq消息已被成功消费,可以删除该消息。否则消息会被标记为unacked状态,不会自动删除
    channel.basic_ack(delivery_tag=method.delivery_tag)

# 生成socket
conn_params = pika.URLParameters('amqp://admin:admin@localhost:5672/%2F')
connection = pika.BlockingConnection(conn_params)
# 生成管道
channel = connection.channel()
# 每次只能从mq获取一条消息,直到channel.basic_ack确认之后,才能认领第二条
channel.basic_qos(prefetch_count=1)
channel.basic_consume(QUEUE, on_message_callback=on_message_callback, auto_ack=False)
channel.start_consuming()
  • 多个消费者订阅同一个queue,同一个消息只能被一个消费者认领
  • 可以通过exchange交换器的fanout模式实现将同一个消息发送给多个消费者

RPC远程过程调用:

将一个函数运行在远程计算机上并且等待从那儿获取结果时,就可以用MQ自带的RPC。换句话说就是生产者发布了一条消息,需要等待消费者返回结果的场景下。

客户端(生产者):

correlation_id = uuid.uuid4()
# 处理服务端返回的结果
def on_message_callback(self, c, method, props, body):
    # 客户端等待回调队列里的数据。当有消息出现的时候,它会检查correlation_id属性。如果此属性的值与请求匹配,则继续处理。
    if correlation_id != props.correlation_id:
        return
    data = json.loads(body.decode(encoding='utf-8'))
    print(data)
    c.basic_ack(delivery_tag=method.delivery_tag)  # 回复确认消息

# 生成socket
conn_params = pika.URLParameters('amqp://admin:admin@localhost:5672/%2F')
connection = pika.BlockingConnection(conn_params)
# 生成管道
channel = connection.channel()
channel.basic_qos(prefetch_count=1)

# 声明一个callback_queue,服务端会将结果发送到这个queue
declared_callback_queue = channel.queue_declare(queue='callback_queue', exclusive=False, auto_delete=False)
# 发送消息给服务端
channel.basic_publish(exchange='',routing_key='task_queue',
                      properties=pika.BasicProperties(
                          # 告诉服务端将返回发到哪个队列
                          reply_to=declared_callback_queue.method.queue,
                          # correlation_id作用是将请求与响应一一匹配
                          correlation_id=correlation_id
                          ),
                      body=json.dumps(body).encode(encoding='utf-8'))    

# 监听callback_queue,处理服务端返回的结果
channel.basic_consume(queue=declared_callback_queue.method.queue, on_message_callback=on_message_callback)
channel.start_consuming()
# 结束监听
#channel.stop_consuming()

服务端(消费者):

def on_message_callback(channel, method, props, body):
    content = json.loads(body.decode(encoding='utf-8'))
    print(f'服务端收到了消息:{content}')
    channel.basic_publish(exchange='',
                          routing_key=props.reply_to, # 这是关键
                          properties=pika.BasicProperties(correlation_id=props.correlation_id),
                          body=json.dumps({'msg': '消息处理成功'}).encode(encoding='utf-8'))

# 生成socket
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', credentials=pika.PlainCredentials('admin', 'admin')))
# 生成管道
channel = connection.channel()
# 声明一个queue
queue = channel.queue_declare(queue='task_queue', exclusive=False, auto_delete=True)
# 处理完这条再发下一条
channel.basic_qos(prefetch_count=1)
# 定义收到消息动作
channel.basic_consume(queue=queue.method.queue, on_message_callback=on_message_callback, auto_ack=True)
channel.start_consuming()

你可能感兴趣的:(MQ,缓存,Redis,celery异步任务,java-rabbitmq,rabbitmq,java)