• home > webfront > ECMAS > npm-node >

    koa服务器后台:Node.js 通过进程、线程优化的性能

    Author:zhoulujun Date:

    node js 单线程的特点在nodejs如何利用多核的优势呢?如何通过多线程提高node js 的性能?当有多个进程监听端口时,Master 进程创建一个 Socket 并绑定监听到该目标端口,通过与子进程之间建立 IPC 通道


    node.js 单线程的特点

    node.js 以异步非阻塞单线程,作为其执行速度的保障。

    • 高性能(不用考虑多线程间来回调用引起性能的损耗)

    • 线程安全(不用担心同意变量会被多线程进行读写而造成程序的崩溃)

    • 底层多线程

      • 说node.js 是单线程其实也是不全面的,node.js 底层库会使用libuv调用多线程来处理I/O 操作。这就像食堂只有一个窗口,只能有按顺序一个个的接收点餐,但是后厨配菜的员工却有很多,他们各司其职保证出餐的速度。

    什么是非阻塞单线程?

    参考:

    弄懂javascript的执行机制:事件轮询|微任务和宏任务|定时器 https://www.zhoulujun.cn/html/webfront/ECMAScript/js6/2015_1110_345.html

    同步与异步:并发/并行/进程/线程/多cpu/多核/超线程/管程 https://www.zhoulujun.cn/html/theory/ComputerScienceTechnology/Constitution/2020_0619_8474.html

    requestIdleCallback对比setTimeout/setImmediate/requestAnimationF https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2019_1220_8488.html

    如何通过多线程提高node.js 的性能

    使用 nodejs 的 koa 框架作为后端服务时,为了充分利用服务器的核数,可以创建与cpu 数量相同的进程数

    创建多进程中可以使用 child_process 也可以使用 cluster。

    但是创建了多个进程后还需要考虑负载均衡。因为 cluster 中自己做了负载均衡的算法: round-robin(新连接由主进程接受,然后由它选择一个可用的 worker 把连接交出去,说白了就是轮转法)所以使用 cluster

    这里创建进程时,让子进程监听同一端口。

    可能会问:多个子进程监听同一端口会报错啊。

    实际上,在 node 中进行了处理。当有多个进程监听端口时,Master 进程创建一个 Socket 并绑定监听到该目标端口,通过与子进程之间建立 IPC 通道之后,通过调用子进程的 send 方法,将 Socket(链接句柄)传递过去。端口只会被主进程绑定监听一次,但是主进程和子进程在建立 IPC 通信之后,发送 Socket 到子进程实现端口共享,在之后 Master 接收到新的客户端链接之后,通过负载均衡技术再转发到各 Worker 进程

    https://nodejs.org/dist/latest-v8.x/docs/api/cluster.html

    const Koa = require('Koa');
    const koaRouter = require('koa-router');
    const numCpus = require('os').cpus().length;
    const cluster = require('cluster');
    if (cluster.isMaster) {
        for (var i = 0; i < numCPUs; i++) {
            cluster.fork();
        }
        // 监听worker
        cluster.on('listening', function (worker, address) {
            console.log(
                'listening: worker ' +
                worker.process.pid +
                ', Address: ' +
                address.address +
                ':' +
                address.port +
                ',' +
                address.addressType
            );
        });
    
        // 监听worker退出事件,code进程非正常退出的错误code,signal导致进程被杀死的信号名称
        cluster.on('exit', function (worker, code, signal) {
            console.log(
                '工作进程 %d 关闭 (%s)(%s). 重启中...',
                worker.process.pid,
                signal || code
            );
    
            cluster.fork();
        });
    } else {
        const app = new Koa();
    
        app.use(cors());
        app.use(bodyParser());
        route(app);
    
        app.listen(3000);
    }


    如何通过多进程提高node.js 的性能

    具体参看:https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html

    main.js

    const Koa = require('Koa');
    const koaRouter = require('koa-router');
    const fork = require('child_process').fork;
    
    const app = new Koa();
    const router = new koaRouter();
    
    app.use(router['routes']());
    router.get('/', function(ctx, next) {
        var worker = fork('./work_fibo.js');
        worker.on('message', function(m) {
            if ('object' === typeof m && m.type === 'fibo') {
                worker.kill();
                ctx.body = m.result.toString();
            }
        });
    
        worker.send({type: "fibo", num: 35}, (err) => {
            console.log(`${err}`);
        });
        console.log(`${worker.pid}`);
    
    });
    
    if (!module.parent) {
        app.listen(8080);
        console.log(`Server was start.`);
    }

    work_fibo.js

    var fibo = function fibo(n) {
        return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
    }
    
    process.on('message', function(m) {   
        if (typeof m === 'object' && m.type === 'fibo') {
            var num = fibo(m.num);
            process.send({type: 'fibo', result: num});
        }
    });
    
    process.on('SIGHUP', function() {
        process.exist();
    });

    参考文章:

    koa cluster 使用多进程 https://blog.csdn.net/qq_42535651/article/details/116610502

    Node.js 通过进程、线程优化的性能 https://www.jianshu.com/p/f25388f030be




    转载本站文章《koa服务器后台:Node.js 通过进程、线程优化的性能》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/nodejs/8830.html