4

我正在使用 PyZMQ 创建请求/回复服务器,并且我试图弄清楚为每个新客户端连接创建线程的行为是否由 PyZMQ 自动处理。最终,我试图弄清楚来自一个需要很长时间才能回复的客户端的请求是否会阻止来自所有其他客户端的请求。

通常,我会在 Python 套接字实例上调用 accept,阻塞直到建立新连接,然后在单独的线程中处理任何新连接。但是,PyZMQ 套接字似乎不支持这样的工作流程。那么,这在 PyZMQ 中是如何处理的呢?如果 PyZMQ REP 套接字有多个连接到它的客户端,它如何正确地将回复路由回发出请求的客户端?而且,我该如何设计我的代码,以便在客户端发出长时间运行的请求时不会阻止来自其他客户端的请求?

我知道我可以使用 PyZMQ 提供的基于 Tornado 的 EventLoop,我只是想更好地了解如果这不是一个选项,它将如何工作。

4

1 回答 1

5

ZeroMQ 公开为“类固醇上的套接字”,但还有另一种实现通信的方法。

首先,忘记连接传统套接字中对等点的线。在 0mq 中,您有一个“量子传送器”,它将您的消息从一段代码传递到另一段代码,对您隐藏实际的传递工作。你不能只问 0mq 有多少客户端连接到套接字或者你是否有客户端。因此,ZeroMQ 不能用作套接字的替代品。

取而代之的是,0mq 给了你一顶魔术师帽子,你可以从中取出一些白兔。想象一下,那顶帽子的底部与一个巨大的管道网络相连,另一边有多个奇妙的工厂。这些工厂有时会送一些东西到你的帽子上,当你从帽子里拿出来时,你会发现自己手里拿着一只兔子,或者一束鲜花或其他东西。您无法确定该物品是从哪个工厂发送的,除非该物品上有明确的标签(即多部分消息的一部分指向消息的来源)。

从帽子中取出兔子后,您可能想要发回一些东西,而 0mq 将针对不同的套接字类型表现不同。对于 REP 套接字,它将直接向消息来源发送答案,因为 DEALER 将在连接的对等点之间循环回答,而 ROUTER 在接收消息时为您提供对等点的确切内部地址的大量知识,并允许您在发送消息时设置明确的目的地。

总而言之,如果您想为每个通信客户端设置一个单独的线程,您需要以下内容:

  • 客户应明确表明自己的身份。
  • 在服务器上,您运行一个接收消息的线程(调度程序),从中获取客户端身份并选择一个线程进行处理。
  • Dispatcher 将此消息发送到线程(或派生一个)并继续为传入消息流提供服务。
  • 线程接收消息,处理它并通过调度程序(如果需要)向客户端发送答案。
  • 调度程序路由对客户端的响应。

这是一种在记住经典套接字知识的情况下实现“zeromq 上的多客户端套接字服务器”的方法。

但这不是解决问题的 0mq 方法。

在 0mq 中,您可以将处理逻辑放在一个线程中(上面示例中的调度程序)并将其实现为循环receive request -> process -> send answer -> receive ...。当处理时间不是问题时非常适合。但是当它是,0mq 风格的解决方案涉及客户端和工作人员(执行实际工作)之间的任务队列代理。然后,broker逻辑比上面提到的receive-answer循环稍微复杂一点,worker的实现方式也是一样的。请参阅 zguide - A Request-Reply Message Broker中的示例

于 2012-10-29T20:32:32.873 回答