使用ZMQ进行双向线程间通信

Using ZMQ for bidirectional inter-thread communication

我是 ZeroMQ 的新手。在过去的几个月里,我一直在阅读文档并试用该库。我目前正在开发一个多线程 C++ 应用程序,并希望使用 ZeroMQ 而不是互斥体在我的主线程和它的一个子线程之间交换数据。

子线程正在处理与外部应用程序的通信。因此,我将需要 queue/sockets 在主线程和它的子线程之间。一封用于外发邮件,一封用于收到邮件。

为了实现这个,我应该使用哪个 zmq 套接字。

提前致谢

从使用共享内存和互斥量转向使用 ZeroMQ,您将进入 Actor 模型编程领域。

在我看来,这是一件相当不错的事情。但是,有一些事情需要注意。

  1. 不再需要互斥锁的唯一原因是您复制数据,而不是共享数据。 'cost' 是复制大量数据比锁定指向共享数据的互斥锁花费的时间长得多。因此,与使用共享内存/互斥锁的等效程序相比,您最终可以得到一个看起来 运行 像狗一样漂亮的 Actor 模型程序。
  2. 需要注意的是,在具有多个 CPU 的 Intel Xeons 等复杂架构上,可以想象,访问共享内存所花费的时间与复制它所花费的时间一样长。这是因为这可能(取决于您有多幸运)意味着跨 QPI 总线的交易。 Actor 模型编程非常适合 NUMA 硬件架构。现代 Intel 和 AMD 架构是 partially/fundamentally、NUMA,但它们 运行 通过 QPI / Hypertransport "fake" SMP 环境的协议。
  3. 我会尽可能避免使用 ZMQ_PAIR 套接字。它们不能跨网络连接工作。这意味着,如果出于任何原因,您的应用程序需要跨多台计算机进行扩展,您就必须重新编写代码。但是,如果您从一开始就使用不同的套接字类型,那么扩展您的应用程序只不过是重新部署您的代码,而不是更改它。仅供参考 nanomsg 对没有此限制。
  4. 一刻也不要假设 Actor 模型编程将解决您所有的问题。它带来了一整套问题。您仍然可以死锁、活锁、自旋锁等。Actor 模型程序的问题在于,这些问题可能会潜伏在您的代码中多年并且永远不会发生,直到有一天网络稍微繁忙一点并且 -bam- 您的程序停止 运行宁...
  5. 不过,有一种Actor模型编程的发展叫做"Communicating Sequential Processes"。这并不能解决这些问题,但是如果您编写的程序中包含这些问题,那么它们肯定会每次都发生。所以你在开发和测试期间发现了问题,而不是五年后。还有一个过程计算,即您可以在编写一行代码之前用代数证明您的设计没有问题。 ZeroMQ 不是 CSP。有趣的是,CSP 正在卷土重来——Rust 和 Go 语言都支持 CSP。但是,他们不会跨网络连接执行 CSP - 这都是进程中的东西。 Erlang 也做 CSP,AFAIK 跨网络连接做。
  6. 假设您已经阅读了所有关于 CSP 的内容并且仍将使用 ZeroMQ,请仔细考虑您计划通过 ZeroMQ 套接字发送的内容。如果它都在同一台机器上的一个程序中,那么发送例如整数数组的副本就可以了。它们在接收端仍然可以解释为整数。但是,如果您希望通过 ZMQ 套接字将数据发送到另一台计算机,则非常值得考虑某种序列化技术。 ZeroMQ 传递消息。为什么不使这些消息成为来自对象序列化程序的字节流?然后你可以保证接收到的消息在反序列化之后,在接收端意味着一些合适的东西,而不是必须解决字节顺序等问题。
  7. 我最喜欢的序列化程序包括 Google Protocol Buffers。它与语言/操作系统无关,为异构系统提供了很多选择。 ASN.1 是另一个非常好的选择,它可以用于大多数重要的语言,并且它有一组丰富的有线格式(包括 XML 和 now/soon、JSON、它提供了一些有趣的互操作选项),并执行约束(Google PBufs 不执行的操作),但如果需要真正好的工具,则往往会花钱。 XML 几乎任何东西都可以理解,但是很臃肿。基本上,值得选择一个不会限制您使用 C# 或 Python 的工具。

祝你好运!