Node.js同步库代码阻止异步执行

时间:2013-11-27 18:07:52

标签: node.js asynchronous blocking nonblocking synchronous

假设您有一个拥有同步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是手动处理我唯一的选项吗?

1 个答案:

答案 0 :(得分:0)

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

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

如果你不担心需要50ms的cpu来执行请求,而是你担心你不能通过处理cpu密集请求来交错处理其他请求,那么你可以将工作分解成小块,并使用setInterval()安排下一个块。但这通常是一个可怕的黑客攻击。最好重新构建应用程序。