Node.js / Electron和Python之间的异步IPC

问题描述 投票:0回答:1

我尝试使用Electron为给定的Python代码构建GUI。数据流实际上很简单:用户与Electron应用程序交互,后者将请求发送到Python API,Python API处理请求并发送回复。

到目前为止,很好。我阅读了不同的主题和博客文章:

  1. ZeroRPC解决方案:

  2. Spawn Python API作为来自node.js的子进程并直接进行通信:
  3. 使用zeroMQ套接字(例如互斥对?)

但是在所有这三种解决方案中,我都在同一时间苦苦挣扎:我必须发出异步请求/答复,因为请求处理可能要花一些时间,并且在这段时间内,可能已经出现了更多的请求。对我来说,这似乎是一种非常常见的模式,但是我什么都没找到,也许我只是不知道我到底在寻找什么。

 Frontend                         Backend

     |                              |
REQ1 |—————————————————————————————>|Process REQ1——--
     |                              |               |
REQ2 |—————————————————————————————>|Process REQ2 --|----—
     |                              |               |    |
REP1 |<————————————————————————————-|REPLY1 <———————     | 
     |                              |                    |
REP2 |<————————————————————————————-|REPLY2 <———————————--
     |                              |

在我看来,最灵活的解决方案是使用3. zeroMQ,但是在websitePython doc上,我只找到了最小的工作示例,其中发送和接收都处于阻塞状态。

有人可以给我一个提示吗?

python sockets electron ipc zeromq
1个回答
0
投票

如果您正在考虑使用ZeroMQ,您将进入Actor模型编程领域。在参与者模型编程中,发送消息的发生与接收消息无关(这两个活动是异步的)。

ZeroMQ通过阻塞意味着什么

当ZeroMQ谈论发送“阻塞”时,这意味着ZeroMQ用于在传输已满之前将消息排队的内部缓冲区,因此它将阻塞发送应用程序,直到此队列中有可用空间为止。清空队列的原因是将较早的消息成功传输到了接收方,该接收方具有接收缓冲区,接收方的应用程序必须将其清空。实际传输消息的是属于ZeroMQ内容的管理线程。

此管理线程是关键部分;它独立于您自己的应用程序线程运行,因此使发送方和接收方之间的通信异步。

您可能想要使用ZeroMQ的反应堆zmq_poll()。通常,在actor模型编程中,您有一个循环,最顶层是对反应堆的调用(在这种情况下为zmq_poll())。 Zmq_poll()告诉您什么时候发生了,但是在这里您主要对它感兴趣,告诉您消息已到达。通常,然后您将读取该消息,对其进行处理(可能涉及发送其他ZeroMQ消息),然后循环回到zmq_poll()。

后端

所以您的后端将是这样的:

while (forever)
{
    zmq_poll(list of input sockets) // allows serving more than one socket
    zmq_recv(socket that has a message ready to read) // will always succeed immediately because zmq_poll() told us there was a message waiting
    decode req message
    generate reply message
    zmq_send(reply to original requester) // Socket should be in blocking mode to ensue that messages don't get lost if something is unexpectedly running slowly
}

[如果您不希望为一个以上的前端提供服务,则更简单:

while (forever)
{
    zmq_recv(req)  // Socket should be in blocking mode
    decode req message
    generate reply message
    zmq_send(reply) // Socket should also be in blocking mode to ensure that messages don't get lost if something is unexpectedly running slow
}

前端

您的前端将有所不同。基本上,您将需要Electron事件循环处理程序来接管zmq_poll()的角色。在Electron中使用的ZeroMQ版本将解决此问题。但是基本上,这将归结为发送ZeroMQ消息的GUI事件回调。当消息从后端到达套接字时,您还必须编写一个回调以使Electron运行。在发送和接收消息之间,前端不会有任何阻塞。

Timing

这意味着您绘制的时序图是错误的。前端可以发送任意数量的请求,但是在离开和到达后端的请求之间没有时间对齐(尽管假设一切运行顺利,第一个请求将立即到达)。发送一个或多个请求后,前端简单地返回到它想要做的所有事情(对于用户界面,通常只是等待事件的事件循环管理器)。

该后端将处于读取/处理/回复,读取/处理/回复的循环中,一次处理一个请求。同样,在离开和随后到达前端的那些答复之间没有时间对准。当答复确实回到前端时,它会唤醒并处理。

© www.soinside.com 2019 - 2024. All rights reserved.