2013-11-27 74 views
0

假设您拥有一个拥有同步API的第三方库。自然地,尝试以异步方式使用它会产生不希望的结果,因为在尝试以“并行”方式执行多个事件时,您会遇到阻塞。Node.js同步库代码阻止异步执行

是否有任何常见模式允许我们以异步方式使用这样的库?

考虑下面的例子(使用async库从NPM为了简洁):

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. 

是叉/加入或产卵工作进程手动我唯一的选择吗?

回答

0

是的,这是您唯一的选择。

如果你需要使用50ms的cpu时间做一些事情,并且需要做10次,那么你需要500ms的cpu时间才能做到。如果您希望在小于500毫秒的挂钟时间内完成此操作,则需要使用更多的cpus。这意味着多个节点实例(或者将工作推出到线程池的C++插件)。如何获取多个实例取决于您的应用程序strucuture,使用child_process.send()提供工作的孩子是一种方式,使用集群运行多个服务器是另一种方式。打破你的服务器是另一种方式。说它是一个图像存储应用程序,并且大多数处理请求的速度都很快,除非有人要求将图像转换为另一种格式,并且这是cpu密集型的。您可以将图像处理部分推入不同的应用程序,并通过REST API访问它,从而使主应用程序服务器响应。

如果您不担心需要50ms的cpu来执行请求,但是您担心的是您无法交叉处理其他请求和处理cpu密集请求,那么您可能会破坏处理成小块,并使用setInterval()安排下一个块。虽然这通常是一个可怕的黑客。更好地重构应用程序。