Node.js发送大量请求时出现请求超时的错误

4

我每50毫秒发送一个请求(即每秒20个请求)来获取网站的Body,但是在执行20到30秒后,每个请求都会出现ETIMEDOUT错误。我已经设置了process.env.UV_THREADPOOL_SIZE = 128;

我尝试将THREADPOOL_SIZE设置为大于128的值。

    for(let i in urls) {
        setTimeout(function() {
            getBody(i); //It is function with a request
        },50*i);
    }

    request({
        url:url,
        method:'GET',
        timeout:3000,
        headers: {
            'Accept': '*/*',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
        }},
        (err,res) => {

包: request

请帮我,我想在一秒钟内发送大量请求。


你可能正在使服务器超负荷运行,或因为请求次数过多而被限制。 - Joe Clay
展示 getBody,我们需要看到你是如何发出请求的,使用了哪个模块,传递了什么参数,请求的超时时间是多少。有多种原因可能导致你遇到了这个错误。同时展示堆栈跟踪,因为它可能是连接超时或读取超时。 - Marcos Casagrande
我已上传代码。 - ksew
1个回答

5

UV_THREADPOOL_SIZE限制在128以内,因此您不能将其增加到超过这个数字。

默认情况下大小为4,但可以通过设置UV_THREADPOOL_SIZE环境变量的任何值(绝对最大值为128)来在启动时更改它。

其次,在request模块中没有timeouts属性,正确的属性名称是:timeout

如果您并行运行多个请求到同一服务器,则将其设置为3000可能太低了,特别是如果服务器无法处理那么多请求。

这可能是您收到许多超时错误的原因之一。因此,首先将该数字增加以查看是否仍然超时。

其次,有两种不同类型的超时:

有两种主要类型的超时:连接超时和读取超时。如果在客户端尝试与远程机器建立连接(对应于套接字上的connect()调用)时达到超时,则会发生连接超时。如果服务器太慢以至于无法及时发送响应的一部分,则会发生读取超时。
您可以通过执行以下操作来检查超时是否为连接超时:
if(err.connect === true) // connection timeout.

此外,如果您正在访问相同的域名,为了提高速度和减少超时次数,您可以解析IP地址,并直接使用IP访问服务器。
更新:请参见https://dev59.com/F1kS5IYBdhLWcg3wN0TA#73581100 我没有测试过这个脚本,但是它可以向您展示如何执行,可能需要进行一些微小的修复。
const dns = require('dns');
const { promisify } = require('util');
const URL = require('url');
const dnsResolve = promisify(dns.resolve);


const ipCache = {};

async getIP(host) {
    
    // Use LRU cache with expiration...

    if(ipCache[host]) // If it's set, it's either the resolved IP or dnsResolve Promise
        return ipCache[host];

    ipCache[host] = dnsResolve(host);

    const [ip] = await ipCache[host]; // Wait until the promise is resolved

    ipCache[host] = ip;

    return ip;
}

async getBody(url) {
    
    const { host } = new URL(url);


    const ip = await getIP(host);

    // Build the URL using the IP address instead of the domain
    request( /* ... */)
}   

你还应该对请求进行限制,因为你可能会淹没自己的网络。如果你在VPS上尝试这个操作,你可能会比在本地机器上运行脚本时遇到更少的超时。

例如,在AWS上有一些网络优化实例,更适合于进行大量请求,使用其中一个实例将允许你发出比在本地机器上更多的成功请求。

所以无论是你自己的网络的限制,还是你向其发出请求的服务器的限制,在这两种情况下,你都需要对请求进行限制以避免错误。


3
不,我只是把库改成了axios,在这个库中就不会出现这个问题。 - ksew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接