【问题标题】:Node.js/Express and parallel queuesNode.js/Express 和并行队列
【发布时间】:2014-04-02 03:54:02
【问题描述】:

我们正在构建一个具有 Node.js 服务器和 Express 的基础架构。

在服务器中,发生的情况如下:

  1. 服务器接受来自客户端的传入 HTTP 请求。
  2. 服务器生成两个文件(这个操作可以“比较长”,也就是0.1秒左右)
  3. 服务器将生成的文件(每个约 20-200 KB)上传到外部 CDN
  4. 服务器响应客户端,其中包括 CDN 上文件的 URI

目前服务器对每个请求都按顺序执行此操作,并且效果很好(Node/Express 可以自动处理并发请求)。但是,随着我们计划的增长,并发请求的数量可能会越来越高,我们相信对我们来说最好实现一个队列来处理请求。否则,我们可能会面临同时运行的任务过多以及与 CDN 的打开连接过多的风险。快速响应客户无关紧要。

我的想法是在节点服务器中有一个单独的部分,其中包含 一些“工人”(2-3,但我们将进行测试以确定同时操作的正确数量)。 因此,新流程看起来像:

  1. 服务器接受客户端的请求后,将操作添加到队列中。
  2. 有 2-3 个(待测试)工作人员从队列中取出元素并执行所有操作(生成文件并将其上传到 CDN)。
  3. 当worker处理完操作(如果在队列中停留比较久也没关系),通知Node服务器(回调),服务器响应客户端(一直在等待同时)。

您如何看待这种方法?你认为它是正确的吗?

最重要的是,这如何在 Node/Express 中实现?

感谢您的宝贵时间

【问题讨论】:

    标签: node.js concurrency express queue


    【解决方案1】:

    您可以将 Kue 模块与 Redis(保存作业的数据库)一起使用来支持队列。 您创建工作并将它们放置在使用 kue 模块中,您可以放置​​多少工人来处理它们。 有用的链接: kue - https://github.com/Automattic/kue

    【讨论】:

      【解决方案2】:

      (回答我自己的问题)

      根据this question on Stack Overflow,我的解决方案是使用Caolan McMahon's async module 实现队列。

      主应用程序将创建作业并将它们推送到队列中,该队列对可以运行的并发作业数量有限制。这允许同时处理任务,但对限制进行严格控制。它的工作方式类似于 Mac OSX 上的 Cocoa 的 NSOperationQueue。

      【讨论】:

        【解决方案3】:

        tldr; 可以使用原生 Node.js cluster module 处理大量并发请求。

        一些序言: Node.js 本身是单线程的。它的Event Loop 使它非常适合同时处理多个请求,即使在其单线程模型中也是如此,这是 IMO 的最佳功能之一。

        真正的交易: 那么,我们如何扩展它以处理更多的并发连接并使用所有可用的 CPU?用cluster module

        此模块将完全按照@Qualcuno 所指出的那样工作,这将允许您在主服务器后面创建多个工作器(也称为进程)以分担负载并更有效地使用可用的 CPU。

        根据Node.js官方文档:

        因为工人都是独立的进程,他们可以被杀死或 根据您的程序的需要重新生成,而不影响其他 工作人员。只要还有一些工人还活着,服务器 将继续接受连接。

        必填示例:

        var cluster = require('cluster');
        var http = require('http');
        var numCPUs = require('os').cpus().length;
        
        if (cluster.isMaster) {
          // Fork workers.
          for (var i = 0; i < numCPUs; i++) {
            cluster.fork();
          }
        
          cluster.on('exit', function(worker, code, signal) {
            console.log('worker ' + worker.process.pid + ' died');
          });
        } else {
          // Workers can share any TCP connection
          // In this case its a HTTP server
          http.createServer(function(req, res) {
            res.writeHead(200);
            res.end("hello world\n");
          }).listen(8000);
        }
        

        希望这是你需要的。

        如果您有任何其他问题,请发表评论。

        【讨论】:

        • 这真的很有趣,谢谢。一个问题:在每个集群内部是否有另一个同时执行多个操作的事件循环?因为我确实希望同时运行多个进程,但我只想要有限数量的进程(比如 2-3 个)。
        • @Qualcuno: 这正是它所做的,它定义了几个工人,每个工人都有自己的 事件循环,这极大地扩展了处理的并发连接。您将拥有多少工人的限制取决于您,您可以随时控制他们。使用cluster.workers,您可以随时了解自己拥有多少,甚至可以访问它们及其属性。
        • 我查看了文档,但我不确定我是否理解这对我有什么帮助。基本上,我正在研究类似 Cocoa 的 NSOperationQueue (与 Grand Central Dispatch 一起)的东西。这似乎只是一种获得更多并发性的方法,还是我错了?
        【解决方案4】:

        为此,我会使用 Heroku 为 Web/Worker Dynos(服务器)提供的那种结构。 Web 服务器可以接受请求并将信息传递给工作人员,工作人员可以进行信息处理和上传。我会让前端站点在套接字 (socket.io) 上侦听外部 CDN 的 url,当上传完成时,它将从工作人员那里触发。希望这是有道理的。

        【讨论】:

        • 感谢您的回答,但我们不能选择使用外部服务(Heroku、Socket.io)。
        • socket.io 不是外部服务,我只是建议 Heroku 实现的工作流。 Socket.io 是一个 Node 模块,您可以在运行节点的同一台服务器上运行它,而 Heroku 正好适合 Web/Worker 类比。即使您必须完全是内部人员,这两个建议仍然有效。
        • 我明白了。那你能详细说明你的答案吗?一些代码示例,或至少一些更多信息/方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-20
        • 2013-04-19
        • 2014-01-27
        • 1970-01-01
        • 2015-01-30
        相关资源
        最近更新 更多