请求大量链接时,节点中的请求行为不一致?

我目前正在使用这段代码连接到一个庞大的链接列表(共2458个链接,在https://pastebin.com/2wC8hwad倾倒),以从众多来源获取提要,并将它们交付给我的用户程序。

它基本上将一个大规模的数组分成多个批次(数组),然后派生一个进程来处理一个批处理,以请求每个存储的链接获得一个200状态码。 只有当一个批次完成时,才会发送下一个批次进行处理,当完成分叉处理时将被断开连接。 然而,我正面临着这个逻辑如何performance出不一致的问题,尤其是它请求代码的部分。

const req = require('./request.js') const process = require('child_process') const linkList = require('./links.json') let processor console.log(`Total length: ${linkList.length}`) // 2458 links const batchLength = 400 const batchList = [] // Contains batches (arrays) of links let currentBatch = [] for (var i in linkList) { if (currentBatch.length < batchLength) currentBatch.push(linkList[i]) else { batchList.push(currentBatch) currentBatch = [] currentBatch.push(linkList[i]) } } if (currentBatch.length > 0) batchList.push(currentBatch) console.log(`Batch list length by default is ${batchList.length}`) // cutDownBatchList(1) console.log(`New batch list length is ${batchList.length}`) const startTime = new Date() getBatchIsolated(0, batchList) let failCount = 0 function getBatchIsolated (batchNumber) { console.log('Starting batch #' + batchNumber) let completedLinks = 0 const currentBatch = batchList[batchNumber] if (!processor) processor = process.fork('./request.js') for (var u in currentBatch) { processor.send(currentBatch[u]) } processor.on('message', function (linkCompletion) { if (linkCompletion === 'failed') failCount++ if (++completedLinks === currentBatch.length) { if (batchNumber !== batchList.length - 1) setTimeout(getBatchIsolated, 500, batchNumber + 1) else finish() } }) } function finish() { console.log(`Completed, time taken: ${((new Date() - startTime) / 1000).toFixed(2)}s. (${failCount}/${linkList.length} failed)`) processor.disconnect() } function cutDownBatchList(maxBatches) { for (var r = batchList.length - 1; batchList.length > maxBatches && r >= 0; r--) { batchList.splice(r, 1) } return batchList } 

下面是request.js,使用针 。 (但是,由于一些奇怪的原因,它可能完全挂在一个特定的网站上,在这种情况下,我只是使用这个解决方法 )

 const needle = require('needle') function connect (link, callback) { const options = { timeout: 10000, read_timeout: 8000, follow_max: 5, rejectUnauthorized: true } const request = needle.get(link, options) .on('header', (statusCode, headers) => { if (statusCode === 200) callback(null, link) else request.emit('err', new Error(`Bad status code (${statusCode})`)) }) .on('err', err => callback(err, link)) } process.on('message', function(linkRequest) { connect(linkRequest, function(err, link) { if (err) { console.log(`Couldn't connect to ${link} (${err})`) process.send('failed') } else process.send('success') }) }) 

从理论上讲,我认为这应该是完美无缺的 – 它产生了一个独立的过程来处理连续批量的肮脏工作,所以它不会超载,并且是超级可扩展的。 然而,当使用完整的链接列表2458共7个批次时,我经常会在几乎所有的试验中随机批量出现大量“套接字挂断”错误 ,类似于如果我全部要求都会发生的情况链接一次。

如果我使用cutDownBatchList函数将批次数减less到1,则几乎在每次试用中都能很好地执行。 这一切都发生在Linux Debian VPS上,在v6.11.2上有两个3.1GHz vCore和4GB RAM的OVH

我还注意到的一件事是,如果我在request.js中为7个批次增加了30000(30秒)的timeout ,它的工作原理是正确的 – 但是如果将其减less到1个批次,它的工作状态就会很好,并且会有更低的timeout 。 如果我也尝试一次执行所有2458个链接,并且更高的超时时间,我也不会遇到任何问题(如果我不能通过批处理链接减less超时,基本上使这个迷你algorithm无用。 这一切都可以追溯到不一致的行为问题。

我可以做的最好的TLDR:试图在一个分叉的subprocess中按顺序批量请求一堆链接 – 几乎每一次都以较低的批次数成功完成,即使行为应该是相同的处理它在隔离批次。

任何帮助将不胜感激解决这个问题,因为我不能为我的生活弄明白!