【问题标题】:Watching NodeJS Clusters For Exit观察 NodeJS 集群退出
【发布时间】:2015-01-30 05:15:17
【问题描述】:

我很难考虑让 node.js 进程(异步)运行但仍触发“退出”状态,以便在 CPU 运行完成后我可以做更多事情。

例如,我有一个 Google Places 爬虫,它可以在所有可用的 CPU 上高效地分发 http 请求。

} else if (cluster.isWorker) {
//  Code to run if we're in a worker process

// Send the object we created above from variables so they're available to the workers
process.on('message', function(clusterDivisionObject) {
    var tempArray;

    // Send the chunk of array appropriate for this cluster to process, then request it's place details
    tempArray = clusterDivisionObject.placeIdArray.splice(((cluster.worker.id * clusterDivisionObject.clusterDivision) - clusterDivisionObject.clusterDivision), clusterDivisionObject.clusterDivision);
    tempArray.forEach(function(arrayItem, index, array){
      request({url: config.detailsRequestURI + '?key=' + config.apiKey + '&placeid=' + arrayItem, headers: config.headers}, detailsRequest);
    });
});
}

这里真正的问题是我发送异步request() 语句的最后一行。代码正确执行,但是一旦我点击回调 (detailsRequest) 做某事(在这种情况下,写入一个 json 文件),我就无法控制退出进程。我的回调函数:

function detailsRequest(error, response, body) {
    if (!error && response.statusCode == 200) {
        var detailsBody = JSON.parse(body);
        ...
    }
}

...不知道什么进程正在运行它或它进行了多少次迭代(在整个tempArray 用尽后触发退出)。那么,假设一个集群正在运行request() for x 长度的tempArray,我如何在tempArray.forEach(){} 完成时触发process.exit(0)

我尝试在 tempArray.forEach(){} 之后直接调用 process.exit(0),但在 request() 甚至运行之前进程就会死掉。 是否有任何有效的方法可以让我更好地观察进程以将其称为退出,或者我是否真的在尝试解决由于request() 是异步的并且可以按任何顺序调用或不调用而无法存在的问题?

【问题讨论】:

    标签: javascript node.js asynchronous


    【解决方案1】:

    您需要异步流控制。在所有请求完成之前,您不希望您的进程退出。相反,您要求节点发送所有这些请求,然后退出该过程。签出async.js 或其他一些流控制库。但是你需要这样的东西:

    var tempArray;
    var counter = 0;
    
    tempArray = []; // same as above
    
    // Without asyncjs
    tempArray.forEach(function(arrayItem, index, array){
      request({url: config.detailsRequestURI + '?key=' + config.apiKey +'&placeid=' + arrayItem, headers: config.headers}, detailsRequest);
    });
    
    function detailsRequest(){ 
     // increment counter and handle response
     // this callback gets called N times.
     counter +=1;
     if(counter >= tempArray.length){ process.exit(0); }
    }
    
    
    //With async.js:
    
    async.map(tempArray, sendRequestFunc, function finalDone(err, results){ 
      // here you can check results array which has response
      // and then exit
      process.exit(0);
    }); 
    
    function sendRequestFunc(el, done){ 
      // done callback as per async docs
      // done must be invoked here or the final callback is never triggered 
      request({url:'same as above'}, done)
    }
    

    请记住,您可能需要针对错误或错误响应添加额外检查并相应地处理这些问题。

    sendRequestFunc 中的 done 回调仅在请求返回响应或错误(异步)时调用,并且仅当所有响应都返回时才调用最后一个异步回调“finalDone”。

    【讨论】:

    • 很有道理,但是当我同时运行多个集群时,它就不能正常工作了。有没有其他方法可以确定范围以使数组保持直线?
    • 如果您能提供一个要点来显示更多您的主/工作代码,那就更好了。当您说“阵列保持笔直”时,我不确定您的意思。你能澄清一下吗?
    • 这是我正在使用的,以防万一:gist.github.com/ShawnStrickland/04bf64352ce35dca660d
    • @ShawnStrickland 让我知道这是否有帮助,否则我会评论要点
    • 我认为这是请求模块的限制,因为它必须是异步的。我想我会重构我的代码以利用存储阵列上的多个并发进程,这样我就可以利用多核性能,但仍然能够轻松地销毁进程,所以什么都没有挂起。
    猜你喜欢
    • 2012-11-12
    • 1970-01-01
    • 2015-11-06
    • 2011-05-17
    • 2018-08-19
    • 2020-11-15
    • 2020-04-08
    • 1970-01-01
    • 2019-05-17
    相关资源
    最近更新 更多