假设我有一个带有 ZeroMQ 接口(interface)的节点(进程、线程等),比方说一个 REP
套接字。这意味着我有一个无限主循环,它在 zmq_recv
或 zmq_poll
函数中休眠。
现在该节点还应该从另一个异步事件接收数据。例如,想象一下键盘按钮按下事件或切换 GPIO 引脚或计时器到期。在等待这些事件时,执行也必须休眠。
应如何编写主循环,使其在任一类型的事件(即消息的接收和异步事件的发生)上唤醒?
我可以想到两种解决方案:
首先,轮询循环,其中以非阻塞方式检查两个事件,我每隔几毫秒运行一次循环。这在处理负载方面似乎不理想。
其次,我将两个事件的阻塞代码移到单独的线程中。相反,在主循环中,我睡在一个信号量(或条件变量)上,它由任一事件的发生发布。这就是我在传统应用程序中采用的方式,但是 ZeroMQ Guide Pieter Hintjens 写的非常明确不使用信号量:
Stay away from the classic concurrency mechanisms like as mutexes, critical sections, semaphores, etc. These are an anti-pattern in ZeroMQ applications.
那怎么办?这里的最佳做法是什么?
最佳答案
根据您的操作系统,系统中的大多数事件都是通过一些文件描述符准备好读取而生成的。这通常是它在 Linux、Unix 等系统上的工作方式。例如,键盘输入通过 STDIN 输入。当然,任何描述的文件描述符都可以包含在 ZMQ 轮询中。
如果事件不是通过可在 ZMQ 轮询中使用的文件描述符引发的(例如,Windows 上的串行端口准备好读取),我通常使用线程将事件转换为通过 ZMQ 发送的消息 socket 。效果很好。变得不可移植,但这是不可避免的。
GPIO 可能更难。如果它没有得到某个将 ISR 集成到操作系统驱动程序堆栈中的驱动程序的支持,那么您将不得不轮询它。
关于multithreading - ZeroMQ:如何处理 ZeroMQ 节点中与消息无关的异步事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50856746/