假设您有一个拥有同步API的第三方库。当然,尝试以异步方式使用它会产生不良结果,因为当您尝试以“并行”方式执行多项操作时会被阻止。
是否有任何常见的模式允许我们以异步方式使用这些库?
考虑以下示例(为简洁起见,使用NPM中的async库):
var async = require('async');
function ts() {
return new Date().getTime();
}
var startTs = ts();
process.on('exit', function() {
console.log('Total Time: ~' + (ts() - startTs) + ' ms');
});
// This is a dummy function that simulates some 3rd-party synchronous code.
function vendorSyncCode() {
var future = ts() + 50; // ~50 ms in the future.
while(ts() <= future) {} // Spin to simulate blocking work.
}
// My code that handles the workload and uses `vendorSyncCode`.
function myTaskRunner(task, callback) {
// Do async stuff with `task`...
vendorSyncCode(task);
// Do more async stuff...
callback();
}
// Dummy workload.
var work = (function() {
var result = [];
for(var i = 0; i < 100; ++i) result.push(i);
return result;
})();
// Problem:
// -------
// The following two calls will take roughly the same amount of time to complete.
// In this case, ~6 seconds each.
async.each(work, myTaskRunner, function(err) {});
async.eachLimit(work, 10, myTaskRunner, function(err) {});
// Desired:
// --------
// The latter call with 10 "workers" should complete roughly an order of magnitude
// faster than the former.
fork / join或者spawning worker是手动处理我唯一的选项吗?
答案 0 :(得分:0)
是的,这是您唯一的选择。
如果你需要使用50ms的CPU时间来做某事,并且需要做10次,那么你需要500ms的CPU时间来完成它。如果您希望在不到500毫秒的挂钟时间内完成,则需要使用更多的cpu。这意味着多个节点实例(或将工作推送到线程池的C ++插件)。如何获取多个实例取决于您的应用程序结构,您使用child_process.send()提供工作的子项是一种方式,使用群集运行多个服务器是另一种方式。打破你的服务器是另一种方式。说它是一个图像存储应用程序,并且主要是快速处理请求,除非有人要求将图像转换为另一种格式并且cpu密集。您可以将图像处理部分推送到另一个应用程序,并通过REST API访问它,让主应用程序服务器响应。
如果你不担心需要50ms的cpu来执行请求,而是你担心你不能通过处理cpu密集请求来交错处理其他请求,那么你可以将工作分解成小块,并使用setInterval()安排下一个块。但这通常是一个可怕的黑客攻击。最好重新构建应用程序。