【问题标题】:ZeroMQ informing clients about each otherZeroMQ 相互通知客户端
【发布时间】:2014-05-22 00:49:24
【问题描述】:

我想在多台工作计算机上并行处理繁重的计算任务,这些工作人员必须在彼此之间共享数据。我有一个服务器,所有工作人员都连接到该服务器并了解他们的“邻居”,以便他们可以连接到他们并交换数据。这是我想到的结构的图片:

如您所见,每个节点都有 4 个邻居(我不想在图片中画更多)。我对套接字类型一点也不固定,我只是认为它们是最好的选择。

但似乎 ZeroMQ 无法将有关一个连接的连接信息传达给另一个连接。由于我认为这实际上是一项相当普遍的任务,因此必须有解决方案。 网络的类型可能会有所不同,它可以是标准的 tcp/ip 网络,其中只有一堆通过路由器连接的计算机,也可以是通过 infiniband 连接的集群。所以基本上我想要的是一个字符串,我可以简单地在一个客户端插入到 connect() 或 bind() 中,而不必担心协议和网络类型以及所有这些东西 - 这正是我理解 zeromq 试图完成的事情.

提前感谢您的回答! :)

编辑:这是我想到的示例性通信:

WorkerMiddle.sendToServer("Hey server, please tell me my neighbours")
Server.sendToWorkerMiddle(Worker.top.connectionInfo())
WorkerMiddle.connectTo(WorkerTop)
Server.sendToWorkerMiddle(Worker.bottom.connectionInfo())
WorkerMiddle.connectTo(WorkerBottom)
Server.sendToWorkerMiddle(Worker.left.connectionInfo())
WorkerMiddle.connectTo(WorkerLeft)
Server.sendToWorkerMiddle(Worker.right.connectionInfo())
WorkerMiddle.connectTo(WorkerRight)

【问题讨论】:

  • 这个范围很广,没有更多信息就无法给出有用的答案。因此,首先read the docs,它们提供了非常丰富的信息,并包含许多 连接模式来完成您正在寻找的那种事情。为了提供更多有用的信息,请提供一些代码来指示 a)您的网络拓扑(物理上,它是如何布局/连接在一起的 b)您正在使用的协议 c)您正在使用什么类型的套接字( pub/sub、rep/req 等)d)谁在绑定和谁在连接,端点是如何命名的
  • 谢谢杰森,我已经做到了。但这就是我能说的全部,因为我会根据某人提供的解决方案来选择套接字类型。但我会尽力澄清它:)
  • 对您的问题的出色更新!我知道您说过您阅读了文档,第 4、7 和 8 章提供了一些概念,可以了解这些更复杂的点对点拓扑,还有一个链接的开源通信模式存储库可能会有所帮助。不过,设计这些东西肯定是最复杂的。我将发布部分答案,然后在我有时间讨论套接字选择和通信策略时将其充实。

标签: zeromq


【解决方案1】:

您对 ZMQ 套接字类型、协议和寻址有些误解。我会先尝试解决这个问题,以便您能够继续前进。

ZMQ 绝对抽象出使用 TCP 等网络协议的细节,但是当你通过网络进行通信时,你仍然必须告诉它使用 TCP,而且你仍然会使用良好的 ol IP 地址或 DNS 名称,可将您的对等方相互连接。

因此,对于您的情况,每个工作节点都有一个 IP 地址和/或 DNS 名称。如果您提前知道这些,您甚至不需要向服务器/主服务器询问它们,您可以立即连接到从一个工作人员到另一个工作人员的 IP 地址。相反,如果服务器/主服务器有此信息而工作人员在启动时没有,那么工作人员可以请求 IP 地址列表,主服务器可以将其发送过来......然后它连接到 IP 地址peer 就像它一样,例如,当它连接到 master 时。

服务器

// obviously this code will change depending on the language/binding that you use
// this is psuedo-code
server = new zmq.socket('ROUTER');
server.bind('tcp://10.20.30.40:55555');

工人1

worker1 = new zmq.socket('REQ');
worker1.connect('tcp://10.20.30.40:55555');

工人2

worker2 = new zmq.socket('REQ');
worker2.connect('tcp://10.20.30.40:55555');

...您指出PAIR 套接字似乎最适合您连接工作人员,但它们仅适用于从一个线程到另一个线程的单个多线程应用程序中的通信,所以它不是你在这里寻找什么。相反,您可能希望每个工作人员都有自己的路由器套接字,并且您可以根据需要创建新的请求套接字来连接到每个对等方:

工人1

worker1 = new zmq.socket('REQ');
peer1 = new zmq.socket('ROUTER');
peer1.bind('tcp://10.20.30.41:44444');
worker1.connect('tcp://10.20.30.40:55555');

peers = worker1.send('tell me my peers');
for (i=0; i<peers.length; i++) {
    peer_array[i] = new zmq.socket('REQ');
    peer_array[i].connect('tcp://' . peers[i]);
}

工人2

worker2 = new zmq.socket('REQ');
peer2 = new zmq.socket('ROUTER');
peer2.bind('tcp://10.20.30.42:33333');
worker2.connect('tcp://10.20.30.40:55555');

peers = worker2.send('tell me my peers');
for (i=0; i<peers.length; i++) {
    peer_array[i] = new zmq.socket('REQ');
    peer_array[i].connect('tcp://' . peers[i]);
}

...这里发生的事情是每个工作人员都在设置一个请求套接字来连接到其他工作人员的路由器。服务器将发送回 ipaddress:port 形式的字符串列表。

在不知道从服务器到工作人员或从工作人员到工作人员传递什么类型的信息的情况下,不可能给出比您可能选择的套接字更好的建议,但至少假设客户端/服务器请求/回复系统类型。

如果您有兴趣,我们可以更深入地了解您为什么会做出这些特定的选择,或者如果您仍然遇到困难,请在 cmets 中告诉我。

【讨论】:

  • 感谢您非常详细的回答!回答您提出的一些问题:我事先不了解网络,所以发现是我想在这里做的事情。之后网络不会改变。唯一要传输的就是大量的浮点数(我正在做流体模拟)。
  • 我刚想到的另一件事:将 PAIR 套接字用于 worker-worker-connection 是否只是“糟糕的风格”,还是有其他一些缺点?我想既然工人关系永远不会改变,我不妨为每个人使用 PAIR-socket,因为它在那里节省了一些逻辑和潜在错误。
  • 好吧,除了文档中的线程间通信之外,明确不鼓励 PAIR 进行任何其他操作,我不记得他们给出了多少详细信息,而且我没有查看它背后的来源,但我可以告诉你:PAIR 失去了 ZMQ“魔法”,它会在出现任何导致连接丢失的网络问题时自动重新连接套接字。这本身就是避免使用它的理由,而不是它的设计目的。
  • 啊,好吧,是的,断开连接的事情是有道理的。您的解决方案似乎也更容易^^
  • 当您坚持使用 REQ-ROUTER 组合时,这相当容易。我可能会写一个关于如何执行 ROUTER-ROUTER 组合的问题/答案,这很容易成为您可以在 ZMQ 中使用的最灵活的组合,您只需管理由库本机处理的细节。通常,在这种情况下,您可以让推荐的插座对之一为您工作。
猜你喜欢
  • 1970-01-01
  • 2017-04-18
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多