为什么在Express Node JS中同时请求相同路由时集群不工作?

yxyvkwin  于 2022-12-29  发布在  Node.js
关注(0)|答案(3)|浏览(224)

我写了一个简单的express应用程序示例,处理2个GET路由。第一个路由包含一个while循环,表示5秒内的阻塞操作。第二个路由只是返回一个Hello world文本。
我还按照Node JS文档的简单指南设置了一个集群。
我尝试的结果是:
1.同时向2个不同的路由器发出2个请求=〉它们按预期独立工作。Route /花了5秒,Route /hello花了几毫秒。
1.对同一路由/同时发出2个请求=〉它们同步工作,一个在5秒后响应,另一个在10秒后响应。

const cluster = require("cluster");
const express = require("express");
const app = express();

if (cluster.isMaster) {
  cluster.fork();
  cluster.fork();
} else {
  function doWork(duration) {
    const start = Date.now();

    while (Date.now() - start < duration) {}
  }

  app.get("/", (req, res) => {
    doWork(5000);
    res.send("Done");
  });

  app.get("/hello", (req, res) => {
    res.send("Hello world");
  });

  app.listen(3000);
}

我希望它能并行处理两个相同路由的请求。有人能解释一下是怎么回事吗?

qv7cva1a

qv7cva1a1#

我希望它能并行处理两个相同路由的请求。有人能解释一下是怎么回事吗?
但实际情况并非如此,因为您已经创建了两个服务器示例(两个事件循环,使用cluster. fork()),所以每个请求都在不同的事件循环(服务器示例)中执行,/hello将向您发出提示请求,而/请求仍将等待5秒才发送响应。
现在,如果您尚未创建群集,则/请求将阻塞事件循环,并且在执行之前(将响应发送到浏览器),/hello不会执行。
/将花费5秒的时间来执行,因为您正在阻塞它在其中执行的事件循环,因此无论您创建单个事件循环还是两个事件循环(使用fork()),它都将在5秒后执行
我在两个不同的浏览器中尝试了您的场景,两个请求都花费了5. 05秒(两个请求都由不同的工作线程同时执行)

const cluster = require("cluster");
const express = require("express");
const app = express();

if (cluster.isMaster) {
  cluster.fork();
  cluster.fork();
} else {
  function doWork(duration) {
    const start = Date.now();

    while (Date.now() - start < duration) {}
  }

  app.get("/", (req, res) => {
    console.log("Cluster ID",cluster.worker.id); // publish the workerid

    doWork(5000);
    res.send("Done");
  });



  app.listen(3000);
}

但是在同一个浏览器中,请求总是发往一个工作线程,该线程只在第一个请求执行完之后才执行第二个请求,所以我想这一切都是关于如何在由cluster.fork()创建的工作线程之间分配请求
引自node docs
群集模块支持两种分配传入连接的方法。
第一种方法(也是除Windows之外所有平台上的默认方法)是循环方法,主进程监听端口,接受新连接,并以循环方式将它们分布到工作进程中,并具有一些内置智能以避免工作进程过载。
第二种方法是主进程创建侦听套接字并将其发送给感兴趣的工作进程。然后工作进程直接接受传入的连接。Node.js不提供路由逻辑。因此,重要的是设计一个应用程序,使其在会话和登录等方面不过于依赖内存中的数据对象。

5tmbdcev

5tmbdcev2#

我运行了你的代码,第一个响应在5秒后出现,另一个在8秒后出现,所以集群是工作的。使用下面的代码找出你机器的核心数。如果是,那么只有一个主线程。

const cpuCount = require('os').cpus().length;
i1icjdpr

i1icjdpr3#

这是由于现代浏览器的聪明。如果你同时在两个不同的标签中发出相同的请求,浏览器会注意到,并等待完成它,然后使用第一个请求该高速缓存数据来响应第二个请求。无论你使用集群或多少个fork()。
要摆脱这一点,只需在网络选项卡中禁用缓存,如下所示:
Disable Cache

相关问题