Nodejs官方cluster测试(2)

Nodejs官方cluster测试(2)

<p>上回测试失败(<a herf=“http://cnodejs.org/topic/5108cbb7df9e9fcc58bbd670”>nodejs cluster测试</a> )的原因总算找到了,不是nodejs的原因,nodejs官方cluster工作良好,问题在于测试方式上,在浏览器中同时开两个相同标签,浏览器只会先发送一个请求,等该请求返回后,在发送第二个,也就是说请求在浏览器端就已经被阻塞了。</p>

<p>所以<a herf=“http://www.nodebeginner.org/index-zh-cn.html#blocking-and-non-blocking”>《Node入门》</a>一文中测试阻塞的方式不完全正确,文中描述的阻塞可能在浏览器端就被阻塞了。</p>

<p>正确的方法是在一个请求返回后不断刷新,或是开不同的浏览器进程。这是开十个woker的输出,可以看到十个woker完美并行执行。</p>

A worker with #2 is now connected to 0.0.0.0:80
A worker with #4 is now connected to 0.0.0.0:80
A worker with #5 is now connected to 0.0.0.0:80
A worker with #8 is now connected to 0.0.0.0:80
A worker with #1 is now connected to 0.0.0.0:80
A worker with #3 is now connected to 0.0.0.0:80
A worker with #6 is now connected to 0.0.0.0:80
A worker with #7 is now connected to 0.0.0.0:80
A worker with #9 is now connected to 0.0.0.0:80
A worker with #10 is now connected to 0.0.0.0:80
Worker #1 has a request
Worker #7 has a request
Worker #6 has a request
Worker #3 has a request
Worker #8 has a request
Worker #5 has a request
Worker #4 has a request
Worker #2 has a request
Worker #10 has a request
Worker #9 has a request
Worker #1 makes a response
Time: 5003ms
Worker #1 has a request
Worker #7 makes a response
Time: 5005ms
Worker #6 makes a response
Time: 5008ms
Worker #3 makes a response
Time: 5004ms
Worker #8 makes a response
Time: 5008ms
Worker #5 makes a response
Time: 5008ms
Worker #4 makes a response
Time: 5004ms
Worker #2 makes a response
Time: 5001ms
Worker #10 makes a response
Time: 5000ms
Worker #9 makes a response
Time: 5000ms

另外,火狐浏览器在一个请求超过一秒并且失败时,会再次发送该请求,但不会发送第三次,所以在模拟宕机的测试中,开一个Firefox的标签,你会发现实际宕掉两个worker。


5 回复

Nodejs官方cluster测试(2)

在上一篇文章中,我们遇到了一些关于Node.js官方Cluster模块测试的问题。经过调查,问题并非出在Node.js本身,而是由于测试方法上的问题。具体来说,浏览器在同一个标签页下只能顺序发送请求,因此即使我们在代码中实现了并行处理,浏览器端的请求依然会被阻塞。

正确的测试方法

正确的测试方法应该是通过不断地刷新页面或者使用不同的浏览器实例来模拟并发请求。这样可以确保每个请求都是独立的,并且能够准确地反映出Node.js Cluster模块的实际性能。

示例代码

下面是一个简单的示例代码,展示如何使用Node.js的Cluster模块创建多个worker,并模拟并发请求。

const http = require('http');
const cluster = require('cluster');

if (cluster.isMaster) {
    // 创建10个worker
    for (let i = 0; i < 10; i++) {
        cluster.fork();
    }

    // 监听所有worker的退出事件
    cluster.on('exit', (worker, code, signal) => {
        console.log(`Worker ${worker.process.pid} died`);
    });
} else {
    // 每个worker的逻辑
    const server = http.createServer((req, res) => {
        console.log(`Worker ${process.pid} has a request`);

        setTimeout(() => {
            res.writeHead(200);
            res.end(`Hello World from Worker ${process.pid}`);
            console.log(`Worker ${process.pid} makes a response`);
        }, 5000); // 模拟耗时操作
    });

    server.listen(8000, () => {
        console.log(`A worker with #${process.pid} is now connected to 0.0.0.0:8000`);
    });
}

解释

  1. 主进程

    • cluster.isMaster 判断当前进程是否为主进程。
    • 使用 cluster.fork() 方法创建10个工作进程。
    • 监听工作进程的退出事件,以便在进程退出时进行相应的处理。
  2. 工作进程

    • cluster.isMaster 返回 false,表示当前进程是工作进程。
    • 创建HTTP服务器,并在接收到请求时打印日志。
    • 使用 setTimeout 模拟一个耗时操作,例如数据库查询或文件读写。
    • 响应客户端请求,并在响应完成后打印日志。

测试步骤

  1. 运行上述代码,启动Node.js应用。
  2. 打开多个浏览器标签,访问 http://localhost:8000
  3. 观察控制台输出,可以看到每个worker独立处理请求,并且请求是并发处理的。

通过这种方式,我们可以更准确地测试Node.js Cluster模块的性能,并避免浏览器端的请求阻塞问题。


多线程/多进程/单线程事件驱动 任何1种都是高性能的

NODE属于第三种, 弄CLUSTER反而享受不了JS的原生特性,徒添消耗

node在什么情况下才会触发切换进程?

CLUSTER跟原生特性没有冲突,可以更充分运用多核硬件。

根据你的描述,Node.js官方的cluster模块可以很好地实现多个工作进程的并行处理。下面是使用cluster模块创建10个工作进程,并且每个工作进程接收到请求时会输出日志信息。

示例代码

const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    console.log(`主进程 ${process.pid} 正在运行`);

    // 创建指定数量的工作进程
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', (worker, code, signal) => {
        console.log(`工作进程 ${worker.process.pid} 已退出`);
    });
} else {
    // 工作进程
    const server = http.createServer((req, res) => {
        console.log(`Worker ${process.pid} 收到请求`);
        setTimeout(() => {
            console.log(`Worker ${process.pid} 完成响应`);
            res.writeHead(200);
            res.end('Hello World\n');
        }, Math.random() * 5000); // 模拟不同的处理时间
    });

    server.listen(8000);
    console.log(`工作进程 ${process.pid} 监听在端口 8000`);
}

解释

  • 主进程:主进程负责启动多个工作进程。这里我们使用os.cpus().length来获取当前机器的CPU核心数,并且根据核心数创建相应数量的工作进程。
  • 工作进程:每个工作进程都监听相同的端口(例如8000),并处理来自客户端的HTTP请求。当接收到请求时,每个工作进程会记录一条日志,并随机模拟不同的处理时间(最多5秒)。

运行和测试

  • 将上述代码保存为cluster-app.js文件。
  • 使用命令行运行该文件:node cluster-app.js
  • 使用不同的工具或浏览器标签并发访问http://localhost:8000,可以看到多个工作进程并行处理请求。

注意事项

  • 在实际生产环境中,为了更好地管理资源和错误处理,建议使用PM2等进程管理工具来代替直接使用cluster模块。
  • 确保在不同的浏览器标签或浏览器实例中并发访问,以避免浏览器端的请求排队现象。
回到顶部