Python ZeroMQ PUSH / PULL - 丢失消息?

时间:2011-07-15 02:47:07

标签: python zeromq

我尝试在python模式下使用zeroMQ PUSH / PULL,每隔几秒发送一次 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位Core Core机器,内存为2 [GB]。

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

2 个答案:

答案 0 :(得分:14)

问题是当程序退出时,套接字立即关闭,垃圾收集的有效LINGER为0(即它抛出任何未发送的消息)。对于较大的消息,这是一个问题,因为它们需要更长的时间来发送,而不是对套接字进行垃圾回收。

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

socket.setsockopt(zmq.LINGER, -1)(这是默认设置)应避免此问题,但由于某些原因我没有时间进行调查。

答案 1 :(得分:1)

可以想象你的内存不足(取决于你如何发送消息,是否消耗得足够快等等)。您可以使用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