面试题答案
一键面试实现思路
- 连接分发:在高并发场景下,需要将客户端的连接请求均匀地分配到多个服务器实例(工作进程)上。
- 健康检查:定期检测各个工作进程的健康状态,确保请求不会被发送到已经出现故障的进程。
- 动态调整:根据工作进程的负载情况(如 CPU 使用率、内存占用等),动态调整分配策略,优先将请求分配到负载较轻的进程。
可能用到的技术
- Cluster 模块:Node.js 内置的 cluster 模块可以轻松创建多个工作进程,利用多核 CPU 的优势,实现负载均衡。它会自动处理工作进程的创建、管理以及连接的分发。
- Round - Robin 算法:一种简单的负载均衡算法,按照顺序依次将请求分配到各个工作进程,实现请求的均匀分配。
- Health Check:通过定期向工作进程发送心跳包,检查其响应情况,判断工作进程是否健康。可以使用
http
模块(如果工作进程提供了健康检查的 HTTP 接口)或者自定义的通信协议。
示例代码框架(基于 TCP 服务器和 Cluster 模块)
const cluster = require('cluster');
const net = require('net');
const os = require('os');
if (cluster.isMaster) {
// 计算 CPU 核心数
const cpuCount = os.cpus().length;
// 创建工作进程
for (let i = 0; i < cpuCount; i++) {
cluster.fork();
}
// 监听工作进程退出事件
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died (code: ${code}, signal: ${signal}), restarting...`);
cluster.fork();
});
// 创建 TCP 服务器,监听端口
const server = net.createServer();
server.listen(3000, () => {
console.log('Master TCP server listening on port 3000');
});
// 将连接分发到工作进程
server.on('connection', (socket) => {
const worker = cluster.workers[Object.keys(cluster.workers)[Math.floor(Math.random() * Object.keys(cluster.workers).length)]];
if (worker) {
worker.send({ type: 'connection', socket: socket });
}
});
} else {
// 工作进程接收来自主进程的连接
process.on('message', (msg) => {
if (msg.type === 'connection') {
const socket = msg.socket;
// 处理客户端连接
socket.on('data', (data) => {
socket.write('You sent: ' + data.toString());
});
socket.on('end', () => {
socket.end();
});
}
});
}
上述代码展示了如何使用 cluster
模块创建一个简单的 TCP 负载均衡服务器。主进程负责监听端口并将客户端连接随机分配到各个工作进程,工作进程负责处理具体的客户端请求。