从单独的进程调用client.query 不会给您带来真正的好处,因为向服务器发送查询已经是 node-pg 中的异步操作。然而,真正的问题是你的回调函数的执行时间很长。回调在主事件循环中同步运行并阻塞其他操作,因此最好将其设为非阻塞。
选项 1:分叉子进程
每次执行回调时都创建一个新进程并不是一个好主意,因为每个 Node.js 进程都需要自己的环境,这很耗时。相反,最好在服务器启动时创建多个服务器进程并让它们同时处理请求。
选项 2:使用 Node.js 集群
幸运的是,Node.js 提供了cluster 接口来实现这一点。集群使您能够从一个主进程处理多个工作进程。它甚至支持连接池,因此您可以简单地在每个子进程中创建一个 HTTP 服务器,传入的请求将在它们之间自动分发(node-pg 也支持池)。
集群解决方案也不错,因为您不必为此对代码进行大量更改。只需编写主流程代码,然后以工作人员的身份启动现有代码。
official documentation on Node.js clusters如果集群的各个方面都解释的很好,这里就不赘述了。只是一个可能的主代码的简短示例:
var cluster = require("cluster");
var os = require("os");
var http = require("http");
if (cluster.isMaster)
master();
else
worker();
function master() {
console.info("MASTER "+process.pid+" starting workers");
//Create a worker for each CPU core
var numWorkers = os.cpus().length;
for (var i = 0; i < numWorkers; i++)
cluster.fork();
}
function worker() {
//Put your existing code here
console.info("WORKER "+process.pid+" starting http server");
var httpd = http.createServer();
//...
}
选项3:拆分结果处理
我认为回调函数执行时间长的原因是您必须处理大量结果行,并且没有机会以更快的方式处理结果。
在这种情况下,使用process.nextTick() 将处理分成几个块也是一个好主意。这些块将在几个事件循环帧中同步运行,但可以在这些块之间执行其他操作(如事件处理程序)。这是代码的粗略(未经测试)草图:
function(err, result) {
var s, i;
s = 0;
processChunk();
// process 100 rows in one frame
function processChunk() {
i = s;
s += 100;
while (i<result.rows.length && i<s) {
//do some stuff with result.rows[i]
i++;
}
if (i<result.rows.length)
process.nextTick(processChunk);
else
//go on (send the response)
}
}
我不是 100% 确定,但我认为 node-pg 提供了一些方法来接收查询结果,而不是作为一个整体,而是分成几个块。这将大大简化代码,因此搜索该方向可能是一个想法......
最终结论
如果新请求仍然需要等待太久,我会首先使用选项 2,然后再使用选项 3。