用Pika 0.9.5向RabbitMQ发送大消息:Rabbit默默地删除了消息

时间:2012-10-01 13:00:45

标签: rabbitmq celery pika

我有一堆芹菜任务,他们将结果发布到RabbitMQ消息队列中。发布的结果可能会变得非常大(高达几兆)。对于是否在RabbitMQ消息中放入大量数据是个好主意,意见不一,但我在其他情况下看到过这项工作,只要内存得到控制,它似乎就有用了。

然而,对于我目前的一系列任务,兔子似乎只是放弃了似乎太大的消息。我把它简化为一个相当简单的测试用例:

#!/usr/bin/env python
import string
import random
import pika
import os
qname='examplequeue'
connection = pika.BlockingConnection(pika.ConnectionParameters(
            host='mq.example.com'))
channel = connection.channel()

channel.queue_declare(queue=qname,durable=True)

N=100000
body = ''.join(random.choice(string.ascii_uppercase) for x in range(N))

promise = channel.basic_publish(exchange='', routing_key=qname, body=body, mandatory=0, immediate=0, properties=pika.BasicProperties(content_type="text/plain",delivery_mode=2))

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

我有一个3节点RabbitMQ群集,每个节点都有mq.example.com个循环。客户端在Ubuntu 12.04上使用Pika 0.9.5,而RabbitMQ集群在Erlang R14B04上运行RabbitMQ 2.8.7。

执行此脚本会打印print语句并退出而不会引发任何异常。该消息永远不会出现在RabbitMQ中。

N更改为10000会使其按预期工作。

为什么?

2 个答案:

答案 0 :(得分:2)

我想你在RabbitMq中遇到了tcp-backpressure mechanizm的问题。你可以阅读http://www.rabbitmq.com/memory.html。 我看到两种解决这个问题的方法:

  1. 添加tcp-callback并重新连接来自rabbit的每个tcp-call
  2. 在将信息发送给兔子之前使用压缩信息,这将更容易推送到兔子。
  3. def compress(s):
         return binascii.hexlify(zlib.compress(s))
    
    def decompress(s):
        return zlib.decompress(binascii.unhexlify(s))
    

答案 1 :(得分:0)

这就是我发送和接收数据包的方式。它比hexlify效​​率更高,因为base64可能使用一个字节,而hexlify需要两个字节来表示一个字符。

import zlib
import base64

def hexpress(send: str):
    print(f"send: {send}")
    bsend = send.encode()
    print(f"byte-encoded send: {bsend}")
    zbsend = zlib.compress(bsend)
    print(f"zipped-byte-encoded-send: {zbsend}")
    hzbsend = base64.b64encode(zbsend)
    print(f"hex-zip-byte-encoded-send: {hzbsend}")
    shzbsend = hzbsend.decode()
    print(f"string-hex-zip-byte-encoded-send: {shzbsend}")
    return shzbsend

def hextract(recv: str):
    print(f"string-hex-zip-byte-encoded-recv: {recv}")
    zbrecv = base64.b64decode(recv)
    print(f"zipped-byte-encoded-recv: {zbrecv}")
    brecv = zlib.decompress(zbrecv)
    print(f"byte-encoded-recv: {brecv}")
    recv = brecv.decode()
    print(f"recv: {recv}")
    return recv

print("sending ...\n")
send = "hello this is dog"
packet = hexpress(send)
print("\nover the wire -------->>>>>\n")
print("receiving...\n")
recv = hextract(packet)