【问题标题】:Python ZeroMQ PUSH/PULL -- Lost Messages?Python ZeroMQ 推/拉——丢失消息?
【发布时间】:2011-07-15 02:47:07
【问题描述】:

我正在尝试在PUSH / PULL 模式下将pythonzeroMQ 一起使用,每隔几秒发送一次大小为4[MB] 的消息。

由于某种原因,虽然看起来所有消息都已发送,但似乎只有其中一些消息已被服务器接收。我在这里想念什么?

这是客户端的代码 -- client.py

import zmq
import struct

# define a string of size 4[MB] 
msgToSend = struct.pack('i', 45) * 1000 * 1000 

context = zmq.Context()
socket = context.socket(zmq.PUSH)
socket.connect("tcp://127.0.0.1:5000")

# print the message size in bytes
print len(msgToSend)

socket.send(msgToSend)

print "Sent message"

这是服务器的代码 -- server.py

import zmq
import struct

context = zmq.Context()
socket = context.socket(zmq.PULL)
socket.bind("tcp://127.0.0.1:5000")

while True:
    # receive the message
    msg = socket.recv()

    print "Message Size is: {0} [MB]".format( len(msg) / (1000 * 1000) )

我错过了什么?如何保证消息始终发送且不丢失?

以防万一,我使用的是Ubuntu 10.04 32 位、具有 2[GB] RAM 的 Core Duo 机器。

注意:我使用RabbitMQ 尝试了相同的示例,一切正常——没有消息丢失。我很困惑,因为我经常听到对zeroMQ的赞美。为什么在RabbitMQ 成功的地方失败了?

【问题讨论】:

    标签: python zeromq


    【解决方案1】:

    问题在于,当程序退出时,套接字会立即关闭并以 0 的有效 LINGER 进行垃圾收集(即,它会丢弃所有未发送的消息)。这对于较大的消息来说是个问题,因为它们发送所需的时间比套接字被垃圾收集所需的时间要长。

    您可以通过在程序退出之前放置sleep(0.1) 来避免这种情况(以延迟套接字和上下文被垃圾收集)。

    socket.setsockopt(zmq.LINGER, -1)(这是默认设置)应该可以避免这个问题,但由于某种原因我没有时间调查。

    【讨论】:

    • cwb,谢谢。它有效,但似乎rabbitMQ 更加可靠。我甚至可以流畅地发送 40-60 [MB] 的数据,而在 zeroMQ 中,事情会卡住/无法可靠地工作。
    • 很公平。在这种情况下,我不知道该怪 0MQ 还是 pyzmq;最终结果对您来说是个麻烦。 0MQ 相对于 RabbitMQ 的优势是否值得当然是您的决定。 40-60MB 的数据对于 0MQ 也不应该是问题;但是这里的东西正在绊倒它......
    • 我知道0MQ 应该可以工作(而且可能比rabbitMQ 工作得更快)——但是,根据我有限的测试,除非需要极速—— rabbitMQ 更可靠。
    • 这个 python 问题似乎也适用于 C++。我遇到了同样的问题,有 2 个线程写入同一个目的地(tcp://host:port),每个线程都在快速创建和销毁套接字。似乎当一个线程销毁其套接字时,它具有销毁来自另一个套接字的未发送消息的副作用(即使“套接字”是线程本地的)。
    【解决方案2】:

    可以想象您的内存不足(取决于您发送消息的方式,它们是否被消耗得足够快,等等)。您可以使用socket.setsockopt(zmq.HWM)HWM 设置为合理的值,并防止 zeromq 在传出缓冲区中存储太多消息。考虑到这一点,考虑稍作修改的示例:

    # server
    ...
    counter = 0
    while True:
        ...receive the message
        counter += 1
        print "Total messages recieved: {0}".format(counter)
    
    # client
    socket.setsockopt(zmq.HWM, 8)
    for i in range(1000):
        socket.send(msgToSend)
    

    然后运行 ​​10 个测试客户端:

    for i in {1..10}; do
        python client.py &
    done
    

    从服务器你可以看到所有的消息都收到了:

    Total messages recieved: 9998
    Total messages recieved: 9999
    Total messages recieved: 10000
    

    【讨论】:

    • zeekay,谢谢。看来rabbitMQ 比zeroMQ 可靠得多。我刚刚成功(虽然花了一些时间)发送 320 [MB]。 zeroMQ 卡住/不能可靠地工作。
    猜你喜欢
    • 2011-07-03
    • 2011-11-20
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多