0MQ: Вы можете отбросить сообщение после тайм-аута в шаблоне REQ / REP? - PullRequest
1 голос
/ 20 февраля 2020

В моих приложениях 0MQ я обычно делаю это, чтобы справиться с тайм-аутом:

import zmq

ctx = zmq.Context()

s = ctx.socket(zmq.DEALER)
s.connect("tcp://localhost:5555")

# send PING request
v = <some unique value>
s.send_multipart(["PING", v])
if s.poll(timeout * 1000) & zmq.POLLIN:
    msg = s.recv_multipart()
    ...

Однако, если сервер не работает и через несколько минут выходит в сеть, 0MQ автоматически переподключится и отправит сообщение. Однако, если я добавлю команду send PING в значение oop (раз в секунду) и сервер не будет работать, то, как только сервер вернется в оперативный режим, я получу следующий вызов recv_multipart() - старые сообщения, которые остались во внутренней очереди 0MQ, когда сервер был в автономном режиме. Потому что меня не волнуют старые сообщения, хотя я мог бы сделать это:


s = ctx.socket(zmq.DEALER)
s.connect("tcp://localhost:5555")

while True:
    # send PING request
    v = <some unique value>
    s.send_multipart(["PING", v])
    if s.poll(timeout * 1000) & zmq.POLLIN:
        msg = s.recv_multipart()
        ...
    else:
        s.close()
        s = ctx.socket(zmq.DEALER)
        s.connect("tcp://localhost:5555")

    time.sleep(1)

Но это плохая идея, через некоторое время ctx.socket поднимает ZMQError: Too many open files. Установка опции сокета ZMQ_LINGER на 0, кажется, здесь помогает, но теперь мне не нравится эта стратегия, она мне кажется неправильной.

Так что в идеале я хотел бы отбросить ранее отправленное сообщение, если прочитано тайм-аут случается. Это а) возможно и б) хорошая идея вообще? Я не уверен, что это было бы правильно, хотя, возможно, 0MQ может физически отправить сообщение, но сервер падает, прежде чем он может что-либо отправить обратно, поэтому удаление будет невозможно, потому что не будет ничего, чтобы отбросить, было бы?

Итак, мой вопрос: что мне делать в этой ситуации? Возможно, я смотрю на эту проблему под неправильным углом?

1 Ответ

1 голос
/ 20 февраля 2020

Q : "Можете ли вы сбросить сообщение после тайм-аута в шаблоне REQ/REP?"

Q : Это а) возможно и б) вообще хорошая идея?

а) Да.
б) Да.

Q : Что мне делать в этой ситуации?

Лучше всего избегать REQ/REP уверенность в том, что вы попали во взаимный тупик (вы просто никогда не знаете, когда это произойдет - многие посты с подробной информацией здесь) + настройте уровень соединений, чтобы обеспечить средства самозащиты для доставки только последнего сообщения через исправное соединение:

...
s = ctx.socket( zmq.DEALER )

s.setsockopt( zmq.LINGER,    0 ) # ALWAYS, no excuse, you never know the peers' versions
s.setsockopt( zmq.IMMEDIATE, 1 ) # prevent sending over incomplete yet connections
s.setsockopt( zmq.CONFLATE,  1 ) # Does not support multi-part, so .pack() payload

s.connect( "tcp://localhost:5555" )
...
...