使用Python和ZeroMQ分发任务

3
我有一个使用 Python 和 ZeroMQ 的工作应用程序,我希望对其进行优化。
简而言之,一个主节点向所有工作节点(约 200 个)发送相同的请求,然后收集答案。基于答案,它向一个节点发送消息,该节点回复答案。
目前,我实现了一个非常简单的模式。每个工作进程都有一个 REP 套接字,服务器有一个 REQ 套接字列表。服务器通过所有套接字进行迭代,发送通用消息,然后通过所有套接字进行迭代以收集答案。最后,基于答案,服务器选择一个进程,向其发送消息并等待回复。
当然,这样做速度相当慢。最慢的部分是发送相同的消息 200 次。收集也很慢。我找到的解决方案可以负载均衡来分配任务和收集答案,但这不是我需要的。我需要每个工作进程都接收消息并响应。
在这种情况下,什么是推荐的模式?
谢谢

你是什么意思,"这种情况下推荐使用什么模式?" - Marcin
例如,如果您需要处理独立的任务,您可以使用通风器模式来分发任务,如此处所述http://taotetek.wordpress.com/2011/02/02/python-multiprocessing-with-zeromq/。 - Hernan
我知道什么是模式。你实际上并没有解释你正在做什么,你当前解决方案的哪些部分是必需的,甚至为什么分发消息很慢。针对“分发东西很慢”的经典解决方案是不要分发东西,或者少分发一些。 - Marcin
1
谢谢你尝试帮我重新思考这个问题,但请给予一些信任。我需要进行分发,因为工人们需要访问不适合在一个节点的RAM中存储的信息(而访问磁盘则太慢了)。分发消息比每个节点的往返时间长两个数量级。这是有道理的,因为我要做200次。该往返时间包括通过网络堆栈进行所有开销。我想知道是否有一种模式可以批处理所有这些调用。 - Hernan
2个回答

2
如果每个工人需要不同的工作,Pub/sub就行不通了。那么你需要的是一个工人池实现。你可以以轮询的方式推送作业(只需使用服务器上的push套接字绑定,并让每个客户端从中拉取,zeromq会进行轮询),或者让每个工人从服务器请求作业,如果作业至少具有一定的复杂度和作业之间的差异很大,那么这是更好的方法。在zeromq指南的主页和网络上有许多例子: 具体的实现还取决于您是否需要可靠地处理作业。

谢谢,但正如我在问题中所描述的那样,每个工人都做同样的事情(但在他们自己的数据部分中)。 - Hernan

0

我不知道zmq。这里有一个可能不起作用的模式,只是为了开始:

主节点向所有工作节点(约200个)发送相同的请求

主节点PUB绑定*:3140发送

工作节点SUB连接masterhost:3140 SUBSCRIBE接收

然后收集答案

工作节点PUSH连接masterhost:3141发送

主节点PULL绑定*:3141接收

根据答案,它向一个节点发送消息,该节点回答。

主节点REQ连接workerhost:3142发送接收

工作节点REP绑定*:3142接收发送


我终于有时间来实现和测试这个了。第一部分(分发相同的任务)比循环200个套接字要快100倍,因为我使用pub/sub进行分发。第二部分(收集答案)仍然相当慢(需要8毫秒)。我正在pull套接字中调用recv 200次。有没有办法告诉zeromq:“等待200条消息并在准备好时将它们作为数组返回”? - Hernan
“等待200条消息并在准备好时将它们作为数组返回”比您目前正在做的事情更快的原因是什么?除非还有其他东西在拖慢速度,否则我认为只有在使用多个线程拉取消息时才会更快,您可以尝试一下。 - Aaron Watters
2
@AaronWatters:0MQ套接字不是线程安全的。请勿在线程之间共享它们。 - jfs
@Hernan:对于一个通用的PULL套接字,每秒25k条消息听起来不错。你是怎么得到“8毫秒”的数字的?你可以尝试调整套接字、操作系统网络选项。在Python中,调用一个虚拟函数200次需要约1微秒的时间。.recv()会释放/重新获取GIL,因此它可能会导致延迟。 - jfs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接