Nodejs 求指导:根据url路由到不同的子进程进行处理
Nodejs 求指导:根据url路由到不同的子进程进行处理
我希望能用一个master生成若干childprocess,由master负责接收request,然后根据url路由到不同的childprocess进行处理(这是由于数据同步要求只能分派到固定的一个process进行处理),这显然无法用cluster解决。当然也可以让子进程侦听不同端口,由master转发request,但这样要引入额外间接层和开销。 是否有高手可以提供指导,不胜感激!
当然可以!你希望使用 Node.js
创建一个主进程 (master
) 和多个子进程 (childprocess
),并且根据请求的 URL 路由到不同的子进程进行处理。以下是一个简单的实现方案,包括基本的代码示例和解释。
实现思路
- 主进程 (
master
): 接收 HTTP 请求并根据 URL 将请求路由到相应的子进程。 - 子进程 (
childprocess
): 处理从主进程接收到的请求,并返回响应。
示例代码
主进程 (master
)
const http = require('http');
const { fork } = require('child_process');
// 创建子进程
const child1 = fork('./child1.js');
const child2 = fork('./child2.js');
// 存储子进程的通信管道
const childProcesses = {
'/path1': child1,
'/path2': child2
};
const server = http.createServer((req, res) => {
const url = req.url;
// 根据URL选择对应的子进程
if (childProcesses[url]) {
childProcesses[url].send({ type: 'request', data: { url, body: '' } });
// 监听子进程的消息
childProcesses[url].on('message', (msg) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(msg.data);
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
子进程 (child1.js
或 child2.js
)
process.on('message', (msg) => {
if (msg.type === 'request') {
// 这里模拟处理请求
const response = `Processed by ${process.pid} for path ${msg.data.url}`;
process.send({ type: 'response', data: response });
}
});
解释
- 主进程 创建了两个子进程 (
child1.js
和child2.js
),并将它们映射到特定的 URL 路径。 - 当主进程接收到请求时,它会根据请求的 URL 选择相应的子进程,并通过进程间的通信 (
IPC
) 发送请求数据。 - 子进程接收到请求后,模拟处理请求,并将结果发送回主进程。
- 主进程接收到子进程的结果后,将其作为 HTTP 响应返回给客户端。
这种方法避免了为每个子进程创建独立的 HTTP 端口,从而减少了额外的复杂性和开销。
手一滑不知为何发了3遍,囧
你的 childprocess 要和 master 是不同的 thread 吗?
是的。事实上,每个childprocess对应我一个独立的数据库,独立进程对于架构的安全和灵活还是很重要的。
这本质上就是所谓的IPC问题(inter-process communication),成熟的解决方案就那几种,具体到nodejs平台上的选择貌似就3种,pipe/socket/unix domain socket,无论怎么折腾,若想把req,res直接传递到子进程,那是门都没有。就楼主的情况,选择unix domain socket吧,它的开销远低于连接数据库的开销,在考虑转发对性能的影响前,先考虑下改善数据库的访问速度吧。
可能有人不知道domain socket是什么玩意,其实就是server监听unix的某个path,与传统的socket区别就是domain socket没有额外的网络数据包开销,直接是内存数据的复制。
http.createServer(function(req,res){
//............
}).listen('/var/tmp/test.sock');
var opts={
socketPath:’/var/tmp/test.sock’
// more options…
}
var req=http.request(opts)
首先感谢shiedman的指导
目前看来传递socket应该是可取的方向,不过考虑到增加了socket路由等一系列的复杂性,所以我打算退而求其次,多开几个http server和端口,利用反向代理来解决问题了
在Node.js中实现根据URL路由到不同的子进程进行处理的需求时,可以通过child_process
模块来创建子进程,并通过IPC(进程间通信)机制来进行消息传递。下面是一个简单的示例,展示了如何根据请求的URL将任务分配给不同的子进程。
示例代码
Master进程 (server.js)
const http = require('http');
const { fork } = require('child_process');
// 创建子进程
const processA = fork('./workerA.js');
const processB = fork('./workerB.js');
const server = http.createServer((req, res) => {
const url = req.url;
if (url.startsWith('/processA')) {
processA.send({ type: 'task', data: url }, req, [req.socket]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Request sent to Process A');
} else if (url.startsWith('/processB')) {
processB.send({ type: 'task', data: url }, req, [req.socket]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Request sent to Process B');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
Worker进程 (workerA.js 和 workerB.js)
以workerA.js
为例:
process.on('message', (msg, socket) => {
if (msg.type === 'task') {
// 处理请求
console.log(`Worker A received task: ${msg.data}`);
socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>Process A Response</h1>');
socket.end();
}
});
workerB.js
的代码与workerA.js
类似,只需修改响应内容。
解释
- Master进程:负责启动HTTP服务器,并根据请求的URL将任务发送给相应的子进程。使用
process.send
方法向子进程发送消息,并通过第三个参数传递socket对象。 - 子进程:监听来自master的消息,并根据接收到的任务类型执行相应的操作。使用
process.on('message')
监听消息,并通过socket对象直接向客户端返回响应。
这种方式避免了为每个子进程单独开启端口的需求,减少了额外的间接层和开销。