Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading ZeroMQ:如何在ZeroMQ节点中处理与消息无关的异步事件?_Multithreading_Asynchronous_Zeromq_Distributed Computing_Distributed System - Fatal编程技术网

Multithreading ZeroMQ:如何在ZeroMQ节点中处理与消息无关的异步事件?

Multithreading ZeroMQ:如何在ZeroMQ节点中处理与消息无关的异步事件?,multithreading,asynchronous,zeromq,distributed-computing,distributed-system,Multithreading,Asynchronous,Zeromq,Distributed Computing,Distributed System,假设我有一个带有ZeroMQ接口的节点(进程、线程等),比如说一个REP套接字。这意味着我有一个无限的主循环,它睡在zmq\u recv或zmq\u poll函数中 现在,该节点还应该从另一个异步事件接收数据。例如,想象一个键盘按钮按下事件或切换GPIO引脚或计时器过期。在等待这些事件时,执行也必须休眠 主循环应该如何写入,以便在任一类型的事件(即接收消息和发生异步事件)时唤醒 我可以想出两种解决办法: 首先是一个轮询循环,其中两个事件都以非阻塞方式进行检查,我每隔几毫秒运行一次循环。就处理负载

假设我有一个带有ZeroMQ接口的节点(进程、线程等),比如说一个
REP
套接字。这意味着我有一个无限的主循环,它睡在
zmq\u recv
zmq\u poll
函数中

现在,该节点还应该从另一个异步事件接收数据。例如,想象一个键盘按钮按下事件或切换GPIO引脚或计时器过期。在等待这些事件时,执行也必须休眠

主循环应该如何写入,以便在任一类型的事件(即接收消息和发生异步事件)时唤醒

我可以想出两种解决办法:

首先是一个轮询循环,其中两个事件都以非阻塞方式进行检查,我每隔几毫秒运行一次循环。就处理负载而言,这似乎并不理想

其次,我将这两个事件的阻塞代码移动到单独的线程中。相反,在主循环中,我在一个信号量(或条件变量)上休眠,该信号量由任一事件的发生来传递。这是我在传统应用程序中所采用的方式,但Pieter Hintjens编写的文章非常明确地指出了不使用信号量:

远离传统的并发机制,比如互斥体, 关键部分、信号量等。这些是中的反模式 ZeroMQ应用程序

那怎么办呢?这里的最佳实践是什么

主循环应该如何写入,以便它在任何类型的事件(即接收消息和发生异步事件)时被唤醒

你几乎回答了自己的问题。并发事件循环是一个问题。ZeroMQ允许处理异步和同步检查的消息队列

考虑到你的控制逻辑需要一些额外的与时间相关的决定,任何人进入任何阻塞状态都是非常糟糕的想法(即使帖子和“帮助”文件中的流行媒体几乎都提供了所有带有阻塞状态SLOC的琐碎代码示例以供“解释”。不,不,不

永远不要失去你的控制角色。第一个阻塞状态会将你的代码从它自己控制的域中移除。不。不。不

这里的最佳实践是什么?

即使您的控制策略是复杂的、细粒度的,无论如何,最好使用显式控制的计时部分,您可以使用{non blocking | controlled duration blocking}-调用
.poll()
,首先检测显式{ACK d | NACK'd}出现任何消息到达,以及下一步您的处理策略可能会根据您的优先级、后处理持续时间和资源可用性状态和/或它们各自处理每个检测到的事件的后处理工作负载的相对性能来决定如何处理检测到的事件组成我在控制回路中的时间很难限制

这就是{软|硬}实时系统的工作方式

ZeroMQ提供了一些技巧来正确和智能地实现这一点(使用零拷贝机制,使用每个相应
Context()的性能/延迟调整选项)
-instance的嵌入式IO线程池,使用几乎零延迟的
inproc://
传输类,在可行的情况下避免老式的并发钟声和哨声…Martin SUSTRIK发布了很多关于性能的信息和更多细节)


奖金部分:
如果您的硬件资源似乎太弱,无法处理任何成熟的fat代理网络,仍然可以使用Zero IO thread
Context()将您的系统组成一个轻量级代理网络
-s,在PROC://-s网格上与系统的作战模拟控制室进行通信,在那里收集和维护态势感知,做出符合全球控制战略的决策,并从那里发出相应的战略、战术和作战命令,为分布式系统进行协调ibution和marshall在轻量级和任务专用的几乎是自治的代理中进行最后的执行。0MQ风格的解决方案是使用第二个套接字通知主线程其他异步事件。然后将这两个套接字传递给
zmq\u poll
,当消息是ava时,将通知主线程可在任意一个插座中使用

例如,除了
REP
套接字之外,主线程还可以创建一个
PULL
套接字。它会将两者传递到
zmq_poll
,然后阻止等待消息。当触发异步事件时,单独的线程可以将
PUSH
套接字连接到
PULL
并将事件数据传递到wai主线程


有关如何轮询多个套接字的详细信息,请参阅。

根据您的操作系统,系统中的大多数事件都是通过一些文件描述符生成的,这些文件描述符可以随时读取。这通常是它在Linux、Unix等上的工作方式。例如,键盘输入通过STDIN输入。当然,任何描述的文件描述符都可以包括在内在ZMQ民意测验中投票

如果事件不是通过ZMQ轮询中可以使用的文件描述符引发的(例如,Windows上的串行端口已准备好读取),我通常使用线程将事件转换为通过ZMQ套接字发送的消息。工作正常。变得不可移植,但这是不可避免的

GPIO可能更难。如果没有某个将ISR集成到操作系统驱动程序堆栈中的驱动程序的支持,那么您将不得不对其进行轮询。

深入研究后,
REQ/REP
可伸缩的正式通信模式原型几乎肯定会从任何旨在将其应用到特定级别的系统设计中避免众所周知,ustness.
REQ/REP
是通往地狱的必经之路-它肯定是