[Node.js] Load balancing a Http server

Let's see how to do load balancing in Node.js.

 

Before we start with the solution, you can do a test to see the ability concurrent requests your current machine can handle.

This is our server.js:

复制代码
const http = require('http');
const pid = process.pid;
// listen the mssage event on the global
// then do the computation
process.on('message', (msg) => {
    const sum = longComputation();
    process.send(sum);
})

http.createServer((req, res) => {
    for (let i = 0; i<1e7; i++); // simulate CPU work
    res.end(`Handled by process ${pid}`)
}).listen(8000, () => {
    console.log(`Started process ${pid}`);
})
复制代码

 

Test 200 concurrent requests in 10 seconds.

ab -c200 -t10 http:localhost:8000/

 

For one single node server can handle 51 requsts / second:

 

Create cluster.js:

复制代码
// Cluster.js
const cluster = require('cluster');
const os = require('os');

// For runing for the first time,
// Master worker will get started
// Then we can fork our new workers
if (cluster.isMaster) {
    const cpus = os.cpus().length;

    console.log(`Forking for ${cpus} CPUs`);
    for (let i = 0; i < cpus; i++) {
        cluster.fork();
    }
} else {
    require('./server'); 
}
复制代码

For the first time Master worker is running, we just need to create as many workers as our cpus allows. Then next run, we just require our server.js; that's it! simple enough!

 

Running:

node cluster.js

When you refresh the page, you should be able to see, we are assigned to different worker.

 

Now, if we do the ab testing again:

ab -c200 -t10 http:localhost:8000/

 

The result is 181 requests/second!

 


 

 

Sometimes it would be ncessary to communcation between master worker and cluster wokers.

Cluster.js:

We can send information from master worker to each cluster worker:

复制代码
const cluster = require('cluster');
const os = require('os');

// For runing for the first time,
// Master worker will get started
// Then we can fork our new workers
if (cluster.isMaster) {
    const cpus = os.cpus().length;

    console.log(`Forking for ${cpus} CPUs`);
    for (let i = 0; i < cpus; i++) {
        cluster.fork();
    }

    console.dir(cluster.workers, {depth: 0});
    Object.values(cluster.workers).forEach(worker => {
        worker.send(`Hello Worker ${worker.id}`);
    })
} else {
    require('./server'); 
}
复制代码

 

In the server.js, we can listen to the events:

复制代码
const http = require('http');
const pid = process.pid;
// listen the mssage event on the global
// then do the computation
process.on('message', (msg) => {
    const sum = longComputation();
    process.send(sum);
})

http.createServer((req, res) => {
    for (let i = 0; i<1e7; i++); // simulate CPU work
    res.end(`Handled by process ${pid}`)
}).listen(8000, () => {
    console.log(`Started process ${pid}`);
})

process.on('message', msg => {
    console.log(`Message from master: ${msg}`)
})
复制代码

 


 

 

A one patical example would be count users with DB opreations;

复制代码
// CLuster.js

const cluster = require('cluster');
const os = require('os');
/**
 * Mock DB Call
 */
const numberOfUsersDB = function() {
    this.count = this.count || 6;
    this.count = this.count * this.count;
    return this.count;
}

// For runing for the first time,
// Master worker will get started
// Then we can fork our new workers
if (cluster.isMaster) {
    const cpus = os.cpus().length;

    console.log(`Forking for ${cpus} CPUs`);
    for (let i = 0; i < cpus; i++) {
        cluster.fork();
    }

    const updateWorkers = () => {
        const usersCount = numberOfUsersDB();
        Object.values(cluster.workers).forEach(worker => {
            worker.send({usersCount});
        });
    }

    updateWorkers();
    setInterval(updateWorkers, 10000);
} else {
    require('./server');
}
复制代码

Here, we let master worker calculate the result, and every 10 seconds we send out the result to all cluster workers.

 

Then in the server.js, we just need to listen the request:

复制代码
let usersCount;
http.createServer((req, res) => {
    for (let i = 0; i<1e7; i++); // simulate CPU work
    res.write(`Users ${usersCount}`);
    res.end(`Handled by process ${pid}`)
}).listen(8000, () => {
    console.log(`Started process ${pid}`);
})

process.on('message', msg => {
    usersCount = msg.usersCount;
})
复制代码

 

posted @   Zhentiw  阅读(236)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2018-03-08 [HTML5] Accessibility Implementation for complex component
2017-03-08 [React] Recompose: Theme React Components Live with Context
2017-03-08 [Angular] Using directive to create a simple Credit card validator
2017-03-08 [Docker] Container & image (docker run)
2017-03-08 [Django] Building the rest API
2016-03-08 [RxJS] Reactive Programming - New requests from refresh clicks -- merge()
2016-03-08 [RxJS] Starting a Stream with SwitchMap & switchMapTo
点击右上角即可分享
微信分享提示