简体   繁体   English

与https模块并发的API请求导致零星的ETIMEDOUT错误

[英]Concurrent API requests with https module results in sporadic ETIMEDOUT errors

I'm making a bunch of calls, and due to the number of retries I've counted 16981 calls to our third party API. 我正在进行大量调用,由于重试的次数,我已经计算了16981次对我们的第三方API的调用。 There shouldn't be more than 1000-1500 calls total, so the overwhelming majority of these are probably retries. 总共不应有超过1000-1500个呼叫,因此其中绝大多数可能是重试。 Very early on I get a 409 back, so my request code retries, which I think causes a cascading problem. 我很早就收到409,所以我的请求代码重试,我认为这会导致级联问题。 After enough calls I hit a ETIMEDOUT error, so I retry again, which is sucking up a ton of execution time. 调用次数过多后,我遇到了ETIMEDOUT错误,因此我再次尝试,这浪费了大量的执行时间。

My ulimit is 4864, so I don't know if that's low enough for it to be the problem. 我的ulimit是4864,所以我不知道它是否足够低而不能成为问题。

How can I refactor my code to handle concurrency better and avoid these constant retries? 如何重构代码以更好地处理并发并避免这些不断重试? I'm still learning and not sure what a good approach to fix this would be. 我仍在学习,不确定如何解决此问题。

Here's my request code: 这是我的请求代码:

'use strict';

const https = require('https');
const Url = require('url');
const util = require('util');

function createRequest(requestUrl, body, requestHeaders, type = 'GET') {
    // Creates a post request at url with the given body

    return new Promise((resolve, reject) => {

        const retry = function() {
            // console.log('retrying...');
            createRequest(requestUrl, body, requestHeaders, type);
        }

        const parsedUrl = Url.parse(requestUrl, true, true);
        const options = {
            hostname: parsedUrl.hostname,
            path: parsedUrl.path,
            method: type,
            headers: requestHeaders
        };
        const req = https.request(options, (res) => {
            // console.log("Retry after: ", res.headers.date);
            let responseString = '';

            res.on('data', (dataChunk) => {
                responseString += dataChunk;
            });

            res.on('end', () => {
                if (res.statusCode === 200) {
                    resolve(responseString);
                } else if (res.statusCode === 409) {
                    setTimeout(function() {
                        return resolve(createRequest(requestUrl, body, requestHeaders, type));
                    }, res.headers['retry-after'] * 1000);
                }
            });
        });

        if (type === 'POST') {
            req.write(JSON.stringify(body));
        }

        req.on('error', (error) => {
            if (error.code === 'ETIMEDOUT') {
                //console.log('Encountered ETIMEDOUT. Retrying call...');
                console.log('MError: ', util.inspect(error, { showHidden: true, depth: 2 }));

                setTimeout(function() {
                    return resolve(createRequest(requestUrl, body, requestHeaders, type));
                }, 1000);
            }
            // reject(error);
        });

        req.end();
    });
}

module.exports = {
    createRequest
};

And the error: 错误:

MError:  { Error: connect ETIMEDOUT 52.49.220.252:443
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1086:14)
  [message]: 'connect ETIMEDOUT 52.49.220.252:443',
  code: 'ETIMEDOUT',
  errno: 'ETIMEDOUT',
  syscall: 'connect',
  address: '52.49.220.252',
  port: 443 }

If it is timing out then you can increase the timeout but https.request() doesn't provide an option for the same. 如果超时,则可以增加超时时间,但是https.request()不能提供相同的选项。 You can use request module for the same and set an upper value of timeout. 您可以使用相同的请求模块并设置超时的上限。 Try out and let me know. 试试吧,让我知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM