使用 ZeroMQ Socket 时,我可以从一个线程 send() 并从另一个线程发送 recv() 到同一个套接字吗?

Posted

技术标签:

【中文标题】使用 ZeroMQ Socket 时,我可以从一个线程 send() 并从另一个线程发送 recv() 到同一个套接字吗?【英文标题】:When using ZeroMQ Socket, Can I send() from one thread and recv() from another to the same socket? 【发布时间】:2014-11-19 03:04:15 【问题描述】:

我找到了question!之前,但我仍然不知道该怎么做,如果我需要使用 ROUTER 到 DEALER 套接字来构建异步客户端/服务器

在使用zeromq之前,当我需要构建一个异步服务器时,我会将socket的读部分和写部分分开。

一个[dispatch] worker 将epoll_wait socket 的read 事件启动[worker] 线程根据msg 做一些工作,

最后,.send() 操作将在同一个套接字的某个不同线程中触发。

读取和发送可以分开在两个不同的线程中。

在 2 个不同线程中为一个套接字接收和发送

是否可以(允许)使用 zeromq 套接字?

实际上我搜索了一些邮件列表并得到否定的答案。

那我想知道如何处理这种情况?

如果一个socket只能使用一个线程,如何提高整个服务器的并行度和吞吐量?

【问题讨论】:

【参考方案1】:

ZeroMQ 布道提倡“零共享 == 不共享任何东西*”

应该阅读它不共享 socket(更确切地说是 a-ZMQ-socket access-point-object ),所以,您不应将代码设计为在多个线程之间“共享”任何套接字。

这并不意味着两个不同的线程或分布式进程不能通过在它们之间设置的单个 ZMQ 套接字相互监听/对话(一个 .bind()-s,另一个 .connect()) .

所以您的 [ROUTER]-__behavioralArchetypePRIMITIVE_> 可以将 .bind() 输出到同一个 ZMQ-socket 对象中,该对象被发布以获取 .connect()-ed在另一端通过 [DEALER]-__behavioralArchetypePRIMITIVE_>(如图 27 Extended REQ / ROUTER | DEALER / REP Pattern)并完成工作。

*)注意事项:

这个零共享规则有一个主要的例外,ZMQ Context 实例可能会在一些 localhost 线程之间故意共享。

【讨论】:

socket 不能被共享,从一个dealer那里收到的msg可以传递到另一个线程吗?我的意思是,味精在一个线程中接收并在另一个线程中使用此味精做一些工作,然后在另一个线程中将味精 rsp 发送回,可以吗?接收工作人员并使用不同的套接字发送工作以接收请求并发送rsp,没有套接字共享。 作为一种基本方法,从 ZMQ 检索到的 MSG 可以以任何方式进行处理。 Socket 是模型的抽象术语,两个 (1:1) 或更多 (1:many) ZMQ 套接字接入点如何使用内部(对于code-designer ) 传输层发送/分发/接收 MSG 数据。因此,使用像 aREQ_pattern_access_point = aZmqCONTEXT.socket( zmq.REQ ) 这样的临时构造函数创建的 ZMQ 套接字访问点永远不应作为参数传递给另一个创建线程的构造函数,因为每个 ZMQ 套接字访问点都不是为共享而设计的(主要避免在 ZeroMQ 中)。【参考方案2】:

您想通过将套接字的发送和接收操作分成两个不同的线程来解决什么问题?是阻塞吗?因为你的单线程在等待响应时不需要阻塞,你只需要使用轮询来继续处理。

您是否希望根据响应在某个单独的线程中完成一些工作?如果是这样,请打开一个从一个线程到另一个线程的 IPC 套接字并以这种方式发送工作。

“ZMQ Sockets”不是你习惯使用的普通sockets,它们更像是“socket-like things”,赋予你某些超能力,但你必须权衡低级别的螺母和螺栓赞成这种抽象。所以,不,您不能在多个线程之间拆分单个套接字,您必须找到其他方式(使用 ZMQ,这对这种事情是否有好处)在线程之间进行通信。

有许多可行的方法可以做到这一点,您选择的方法将取决于您的用例的具体情况。

【讨论】:

是的,我想把整个msg传输层封装起来,和app层分开。简化进程间结构:所有的msg都可以从zeromq通道中通过一个N:1队列接收,所有的msg都可以在一个主线程中处理,然后rsp可以被主线程放入zeromq传输层, zeromq 可以帮助我发回 rsp。我知道这将是一个效率低下的解决方案,但如果我不太关心效率,我更关心整个流程结构的简单性。 好吧,您可以大致了解您所追求的,只是不能在线程之间拆分 ZMQ 套接字的发送和接收部分。【参考方案3】:

在线程之间共享套接字肯定会失败,正如 zmq 指南 clearly states。

我最近为一个应用程序实现了类似的东西。线程接收消息并通过 INPROC 套接字将它们传递给处理它们的线程。原因是当另一个线程仍在处理某些事情时我仍然可以接收消息(我使用工业系统的 API)。我将自己定位在multi-threaded server example。我强烈建议看看它。我的方法是相反的(我的“主要”方法是工作例程,单独的线程接收消息),但这并不重要。

【讨论】:

在您的多线程服务器示例中,所有工作都可以在“main”方法(工作例程)中完成,如果工作例程无法完成有关此请求的所有任务,工作例程需要把req交给另外一个worker比如workroutine2(main2)来为这个req做step2流程,然后workroutine2负责为这个req发送rsp,你会怎么改例子? 您的示例链接已损坏。请修复它:)

以上是关于使用 ZeroMQ Socket 时,我可以从一个线程 send() 并从另一个线程发送 recv() 到同一个套接字吗?的主要内容,如果未能解决你的问题,请参考以下文章

zeromq怎样获取已经绑定的socket节点

nc访问的ZeroMQ IPC Unix Domain Socket

如何在同一个进程中操作多个 ZeroMQ Socket 类型?

PyZMQ ( ZeroMQ ) - 如何从 SUB 套接字获取订阅密钥?

使用ZeroMQ(clrzmq)实现异步通信

关于 ZeroMQ 并使用替代存储来存储消息