【发布时间】:2021-02-02 19:18:49
【问题描述】:
我有一个包含 URL 的大数组(大约 9000 个元素)的 NodeJS 项目。将使用 request-promise 包请求这些 URL。但是,服务器或客户端都不喜欢来自同一客户端的同一网站的 9000 个并发 GET 请求,因此我想随着时间的推移将它们分散开来。我环顾四周,发现Promise.map 和{concurrency: int} 选项here,听起来就像我想要的一样。但我无法让它工作。我的代码如下所示:
const rp = require('request-promise');
var MongoClient = require('mongodb').MongoClient;
var URLarray = []; //This contains 9000 URLs
function getWebsite(url) {
rp(url)
.then(html => { /* Do some stuff */ })
.catch(err => { console.log(err) });
}
MongoClient.connect('mongodb://localhost:27017/some-database', function (err, client) {
Promise.map(URLArray, (url) => {
db.collection("some-collection").findOne({URL: url}, (err, data) => {
if (err) throw err;
getWebsite(url, (result) => {
if(result != null) {
console.log(result);
}
});
}, {concurrency: 1});
});
我想我可能误解了如何处理承诺。在这种情况下,我会认为,将并发选项设置为 1,数组中的每个 URL 将依次用于数据库搜索,然后作为参数传递给 getWebsite,其结果将显示在其回调中功能。然后将处理数组中的下一个元素。
实际发生的情况是,一些(可能是 10 个)URL 被正确获取,然后服务器开始偶尔响应 500 内部服务器错误。几秒钟后,我的电脑死机,然后重新启动(我猜这是由于某种恐慌?)。
我该如何解决这个问题?
【问题讨论】:
-
9000 个请求?那太多了。我会退后一步,考虑是否有更合适的方法——比如在另一台服务器上设置一个 API,可以一次响应多批数据。
-
是的,它很难看,但它有点像一次性的网络抓取,如果我能设法随着时间的推移将它分散开来,这可能需要一整天的时间才能完成。但是,正如您所说,可能还有其他更好的方法不需要一次发送所有 9000 个请求。
-
好吧,这很合理。
findOne的大量并行调用是否存在问题? -
我不完全确定是什么导致我的计算机出现这种情况。据我所知,
getWebsite中的rp承诺是产生错误消息的原因。数据库是本地的,所以并行findOne调用不应该成为瓶颈,但有可能。
标签: javascript node.js concurrency promise request-promise