Python ZeroMQ PUSH / PULL - потерянные сообщения? - PullRequest
8 голосов
/ 15 июля 2011

Я пытаюсь использовать python с zeroMQ в режиме PUSH / PULL, отправляя сообщения размером 4 [МБ] каждые несколько секунд.

По какой-то причине, покапохоже, что все сообщения отправлены, ТОЛЬКО НЕКОТОРЫЕ из них, по-видимому, были получены сервером.Что мне здесь не хватает?

Вот код для клиента - 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 Duo с 2 [ГБ] ОЗУ.

ПРИМЕЧАНИЕ: Я попробовал тот же пример , используя RabbitMQ, и все работает хорошо - сообщение не теряется.Я в недоумении, так как часто слышу похвалы zeroMQ.Почему это не удалось там, где RabbitMQ удалось?

Ответы [ 2 ]

14 голосов
/ 15 июля 2011

Проблема в том, что когда программа закрывается, сокет немедленно закрывается и мусор собирается с эффективным LINGER, равным 0 (т.е. он выбрасывает все неотправленные сообщения).Это проблема для больших сообщений, потому что для их отправки требуется больше времени, чем для сбора мусора в сокете.

Этого можно избежать, поставив sleep(0.1) непосредственно перед выходом программы (чтобы задержать сокет).и контекст - сборщик мусора).

socket.setsockopt(zmq.LINGER, -1) (по умолчанию) должен избежать этой проблемы, но по какой-то причине у меня нет времени исследовать.

1 голос
/ 15 июля 2011

Возможно, вам не хватает памяти (в зависимости от того, как вы отправляете сообщения, достаточно ли быстро они используются и т. Д.). Вы можете использовать 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
...