如果在Docker中运行,ZeroMQ REQ .recv()会挂起大于〜1kB的消息

时间:2017-11-22 15:43:46

标签: python docker zeromq pyzmq

我正在使用REQ / ROUTER套接字处理基于Python / ZeroMQ的相对简单的工作分配系统。系统是分布式的,工作节点在地理上分布在不同的大陆上。

负责分发工作的ROUTER .bind() -s ROUTER套接字。工作人员使用.connect()套接字通过TCP REQ

在设置新工作节点的过程中,我注意到虽然较小的消息(最多1kB)没有问题但是回复了〜{2kB及以上,由{{1}发送工作人员从未收到-end到ROUTER - 套接字 - 当我调用REQ时,套接字就会挂起。

工作者代码在Docker容器中运行,当我使用recv()运行相同的图像时,我能够解决这个问题 - 如果Docker使用主机网络,似乎不会发生这种情况。

我想知道这是主机或Docker中的网络堆栈配置中的某些内容,还是可以在我的代码中阻止的内容?

以下是我的代码的简化版本,可以重现此问题:

工人

--net=host

路由器

import sys
import zmq
import logging
import time

READY = 'R'

def worker(connect_to):
    ctx = zmq.Context()
    socket = ctx.socket(zmq.REQ)

    socket.connect(connect_to)
    log = logging.getLogger(__name__)

    while True:
        socket.send_string(READY)
        log.debug("Send READY message, waiting for reply")
        message = socket.recv()
        log.debug("Got reply of %d bytes", len(message))
        time.sleep(5)


if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    worker(sys.argv[1])

FWIW我能够使用Docker import sys import zmq import logging REPLY_SIZE = 1024 * 8 def router(bind_to): ctx = zmq.Context() socket = ctx.socket(zmq.ROUTER) socket.bind(bind_to) poller = zmq.Poller() poller.register(socket, zmq.POLLIN) log = logging.getLogger(__name__) while True: socks = dict(poller.poll(5000)) if socks.get(socket) == zmq.POLLIN: message = socket.recv_multipart() log.debug("Received message of %d parts", len(message)) identity, _ = message[:2] res = handle_message(message[2:]) log.debug("Sending %d bytes back in response on socket", len(res)) socket.send_multipart([identity, '', res]) def handle_message(parts): log = logging.getLogger(__name__) log.debug("Got message: %s", parts) return 'A' * REPLY_SIZE if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) router(sys.argv[1]) ,libzmq 17.09.0-ce和PyZMQ 4.1.5在Ubuntu 16.04(路由器和工作人员)上重现这一点。

1 个答案:

答案 0 :(得分:0)

不,先生,套接字根本不会挂起:

为什么?

问题是,您已经指示 Socket() -instance进入无限阻止状态,一旦调用 .recv() 方法,未指定 zmq.NOBLOCK 标志(ZeroMQ原始API中的ZMQ_DONTWAIT标志)。

这是原因,在昨天报告的其他情况下,将代码移动到无限阻塞,因为似乎有其他问题阻止Docker-container正确地将任何第一条消息传递给Worker的Docker嵌入式 - ZeroMQ - Context() I / O引擎以及 REQ -access-point。由于 REQ -archetype使用严格的两步有限状态自动机 - 严格跨步(.send() - > .recv() - > {{1 }} - > .send() ad infimum)

这种原因 - >效应逆转是错误的和误导性的 -
套接字只是挂起 ”的问题 无法决定
来自问题 Docker不提供单个消息(允许...返回)

后续步骤:

可以在 .recv() -side中使用 .poll() 来嗅探工作中任何已经到达的消息。

一旦没有这样的话,首先关注Docker + next可能会受益于ZeroMQ REQ -I / O引擎性能和链接级调整配置选项。