从一个单独的进程调用client.query
并不能给你带来真正的好处,因为在node-pg中向服务器发送查询已经是异步操作了。然而,真正的问题在于回调函数的长时间执行。回调在主事件循环中同步运行并阻塞其他操作,因此最好将其设置为非阻塞。
选项1:分叉子进程
每次执行回调时创建一个新进程并不是一个好主意,因为每个Node.js进程都需要自己的环境,这需要耗费时间来设置。相反,最好在服务器启动时创建多个服务器进程,并让它们同时处理请求。
选项2:使用Node.js集群
幸运的是,Node.js提供了cluster
接口来实现这一点。集群使您能够从一个主进程处理多个工作进程。它甚至支持连接池,因此您可以在每个子进程中简单地创建HTTP服务器,传入的请求将自动分配给它们(node-pg也支持连接池)。
集群解决方案也很好,因为您不必在代码中进行大量更改。只需编写主进程代码并将现有代码作为工作进程启动即可。
Node.js 集群的官方文档非常详细地解释了集群的各个方面,因此我在这里不会详细介绍。这里只提供一个可能的主代码的简短示例:
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");
var numWorkers = os.cpus().length;
for (var i = 0; i < numWorkers; i++)
cluster.fork();
}
function worker() {
console.info("WORKER "+process.pid+" starting http server");
var httpd = http.createServer();
}
选项3:拆分结果处理
我假设回调函数执行时间长的原因是您需要处理大量的结果行,而且没有机会以更快的方式处理结果。
在这种情况下,使用process.nextTick()
将处理拆分成几个块也是一个不错的主意。这些块将在几个事件循环帧中同步运行,但其他操作(如事件处理程序)可以在这些块之间执行。以下是代码的粗略(未经测试)草图:
function(err, result) {
var s, i;
s = 0;
processChunk();
function processChunk() {
i = s;
s += 100;
while (i<result.rows.length && i<s) {
i++;
}
if (i<result.rows.length)
process.nextTick(processChunk);
else
}
}
我不是100%确定,但我认为node-pg提供了一种接收查询结果的方式,不是作为一个整体,而是分成几个块。这将大大简化代码,因此可能是在这个方向上搜索的一个想法...
最终结论
我首先会使用选项2,如果新请求仍然需要等待太长时间,则另外使用选项3。