如何将Node.js集群与ZeroMQ回复工作者一起使用

pap*_*boy 2 javascript sockets zeromq node.js

基本问题是"如何将ZeroMQ REPLY套接字设置为工作者?".

实际上,如何使用具有ZeroMQ REPLY服务器的HTTP服务器替换默认示例,例如:

var cluster = require('cluster'),
    zmq = require('zmq');

if (cluster.isMaster) {
  cluster.fork();
  cluster.fork();
}
else {
  // Using `http.createServer(..).listen(5555);` works perfectly

  // However, the following does not:
  var socket = zmq.socket('rep');
  socket.bind( "tcp://*:5555", function (err) { console.log(process.pid, err); } );
}
Run Code Online (Sandbox Code Playgroud)

第一个worker记录'undefined'(即没有错误),而第二个worker记录错误:Address already in use.

从" 工作原理 "文档来看,这里似乎合适的一点(重点补充):

当您调用server.listen(...)worker时,它会序列化参数并将请求传递给主进程.如果主进程已经具有与工作者要求匹配的侦听服务器,则它将句柄传递给工作者.如果它还没有匹配该要求的侦听服务器,那么它将创建一个,并将句柄传递给worker.

如何"匹配要求"与ZeroMQ REPLY插座?

Jas*_*son 7

你似乎正走在一条略显复杂的道路上.这是你应该注意的第一件事:

  • node.js 的httpcluster模块是内置的,这意味着它们可以以某些方式一起工作,这些方式对于外部/第三方模块是不可用的.
  • zmq绑定模块是一个第三方的模块,这样就不会享受同样的效率和抽象,你通过合并得到httpcluster
  • 在任何情况下,ZMQ都不是HTTP的替代品(以防万一您认为可能,从您的问题中不清楚)

...结果是你不能bind()在同一个地址/端口上并且有节点"序列化参数"或"将请求传递给主进程",并且主进程不能"创建(绑定)服务器匹配工作者的要求并将句柄传递给工作人员"......这不是ZMQ绑定的工作方式,而且需要cluster从内部zmq进行仿效,以便以这种方式工作.

您不能在节点中以这种方式使用ZeroMQ.

但是有好消息!

我们在节点中使用HTTP服务器执行此类过程的原因是因为它提供了更多带宽来提供更多数量的请求.通常,您将收到HTTP请求,您将以某种方式处理和处理该请求.当您执行此过程时会出现轻微延迟,在高流量情况下,可能会阻止您的服务器接收新请求.输入cluster.通过在单独的工作程序中启动多个侦听器,在处理一个请求时,下一个工作人员可以立即处理下一个请求...并且实际上可以减少更多的流量.

你不需要担心ZMQ:

  • 您的单个ZMQ套接字应该能够处理大量吞吐量,每秒数十万甚至数百万条消息.
  • ZMQ的"Q"部分允许这样 - 消息被接收到内部队列,然后将它们从该队列中拉出来处理它们,因此当你处理时,你永远不会(*)阻止接收新消息其他的.
  • 如果你绝对需要进行一些并行化以增加带宽(这不是不可能的,但是你不应该过早地优化这个......除非你知道你在狭窄的人群中会遇到它,否则不解决问题) ,然后你可以绑定多个地址/端口,并使用内置的ZMQs更高级套接字(DEALER等)的循环,或使用更高级的消息模式来实现您的并行化效果.

(*) - 您可以重载系统并删除新消息,具体取决于您的内存和处理限制以及消息的大小.这是高水印的目的.遇到这种限制是切合实际的,但处理它是特定于您的情况,而不是在您当前问题的范围内.


那么,答案是什么?

答案是您通常不需要cluster在节点zmq应用程序中使用来实现服务器并行化.如果你真的想要,你可以近似这种结构...但你通常最好在你的主人中编写你的应用程序,如果你发现自己需要并行执行处理器密集型任务,那么工作者处理完成后返回/退出的特定任务,或者更好的是,用更高效的语言(如C++)编写处理器密集型代码,编写利用节点固有优势并卸载其弱点的异步模块.