我正在使用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(路由器和工作人员)上重现这一点。
答案 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引擎性能和链接级调整配置选项。