Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js获取请求ETIMEDOUT&;埃索克提米德酒店_Javascript_Node.js_Node Request - Fatal编程技术网

Javascript Node.js获取请求ETIMEDOUT&;埃索克提米德酒店

Javascript Node.js获取请求ETIMEDOUT&;埃索克提米德酒店,javascript,node.js,node-request,Javascript,Node.js,Node Request,我正在使用Node.js-async&request模块抓取1亿多个网站,几分钟后我不断遇到错误ESOCKETTIMEDOUT&ETIMEDOUT 重新启动脚本后,它会再次工作。这似乎不是连接限制问题,因为我仍然可以毫不延迟地执行resolve4、resolveNs、resolveMx和curl 你认为代码有什么问题吗?或者有什么建议?我想将async.queue()并发性提高到至少1000。多谢各位 var request = require('request'), async = r

我正在使用Node.js-async&request模块抓取1亿多个网站,几分钟后我不断遇到错误
ESOCKETTIMEDOUT
&
ETIMEDOUT

重新启动脚本后,它会再次工作。这似乎不是连接限制问题,因为我仍然可以毫不延迟地执行resolve4、resolveNs、resolveMx和
curl

你认为代码有什么问题吗?或者有什么建议?我想将async.queue()并发性提高到至少1000。多谢各位

var request = require('request'),
    async = require('async'),
    mysql = require('mysql'),
    dns = require('dns'),
    url = require('url'),
    cheerio = require('cheerio'),
    iconv = require('iconv-lite'),
    charset = require('charset'),
    config = require('./spy.config'),
    pool = mysql.createPool(config.db);

iconv.skipDecodeWarning = true;

var queue = async.queue(function (task, cb) {
    dns.resolve4('www.' + task.domain, function (err, addresses) {
        if (err) {
            //
            // Do something
            //
            setImmediate(function () {
                cb()
            });
        } else {
            request({
                url: 'http://www.' + task.domain,
                method: 'GET',
                encoding:       'binary',
                followRedirect: true,
                pool:           false,
                pool:           { maxSockets: 1000 },
                timeout:        15000 // 15 sec
            }, function (error, response, body) {

                //console.info(task);

                if (!error) {
                  // If ok, do something

                } else {
                    // If not ok, do these

                    console.log(error);

                    // It keeps erroring here after few minutes, resolve4, resolveNs, resolveMx still work here.

                    // { [Error: ETIMEDOUT] code: 'ETIMEDOUT' }
                    // { [Error: ESOCKETTIMEDOUT] code: 'ESOCKETTIMEDOUT' }

                    var ns = [],
                        ip = [],
                        mx = [];
                    async.parallel([
                        function (callback) {
                            // Resolves the domain's name server records
                            dns.resolveNs(task.domain, function (err, addresses) {
                                if (!err) {
                                    ns = addresses;
                                }
                                callback();
                            });
                        }, function (callback) {
                            // Resolves the domain's IPV4 addresses
                            dns.resolve4(task.domain, function (err, addresses) {
                                if (!err) {
                                    ip = addresses;
                                }
                                callback();
                            });
                        }, function (callback) {
                            // Resolves the domain's MX records
                            dns.resolveMx(task.domain, function (err, addresses) {
                                if (!err) {
                                    addresses.forEach(function (a) {
                                        mx.push(a.exchange);
                                    });
                                }
                                callback();
                            });
                        }
                    ], function (err) {
                        if (err) return next(err);

                        // do something
                    });

                }
                setImmediate(function () {
                    cb()
                });
            });
        }
    });
}, 200);

// When the queue is emptied we want to check if we're done
queue.drain = function () {
    setImmediate(function () {
        checkDone()
    });
};
function consoleLog(msg) {
    //console.info(msg);
}
function checkDone() {
    if (queue.length() == 0) {
        setImmediate(function () {
            crawlQueue()
        });
    } else {
        console.log("checkDone() not zero");
    }
}

function query(sql) {
    pool.getConnection(function (err, connection) {
        if (!err) {
            //console.log(sql);
            connection.query(sql, function (err, results) {
                connection.release();
            });
        }
    });
}

function crawlQueue() {
    pool.getConnection(function (err, connection) {
        if (!err) {
            var sql = "SELECT * FROM domain last_update < (UNIX_TIMESTAMP() - 2592000) LIMIT 500";
            connection.query(sql, function (err, results) {
                if (!err) {
                    if (results.length) {
                        for (var i = 0, len = results.length; i < len; ++i) {
                            queue.push({"id": results[i]['id'], "domain": results[i]['domain'] });
                        }
                    } else {
                        process.exit();
                    }
                    connection.release();
                } else {
                    connection.release();
                    setImmediate(function () {
                        crawlQueue()
                    });
                }
            });
        } else {
            setImmediate(function () {
                crawlQueue()
            });
        }
    });
}
setImmediate(function () {
    crawlQueue()
});
系统控制

net.ipv4.ip_local_port_range = 10000    61000
默认情况下,节点具有。如果您的DNS查询需要很长时间,请求将在DNS阶段被阻止,症状就是
ESOCKETTIMEDOUT
ETIMEDOUT

尝试增加uv线程池大小:

export UV_THREADPOOL_SIZE=128
node ...
或者在
index.js
中(或者您的入口点在哪里):


编辑:关于它。

我也有同样的问题。读取后,通过在请求选项中使用“agent:false”来解决此问题

2017年10月31日 上述最初的回答似乎不能完全解决问题。我们找到的最终解决方案是在代理中使用keepAlive选项。例如:

var pool = new https.Agent({ keepAlive: true });

function getJsonOptions(_url) {
    return {
        url: _url,
        method: 'GET',
        agent: pool,
        json: true
    };
}
节点的默认池似乎默认为keepAlive=false,这会导致在每个请求上创建一个新连接。如果在短时间内创建了太多连接,则会出现上述错误。我的猜测是,服务路径上的一个或多个路由器阻塞了连接请求,可能是因为怀疑存在拒绝服务攻击。无论如何,上面的代码示例完全解决了我们的问题。

在请求工具()

默认情况下,http连接保持活动状态处于关闭状态


您需要设置option.forever=true以打开此功能。

TL:DR在循环之前,仅使用您的设置配置一次
request
的包装器,并使用
forever:true
设置

const customRequest=request.defaults({forever:true});//包装纸
customRequest({uri:uri});
详细的回答
我在循环中执行请求时遇到了完全相同的问题。然而,以上这些对我都不起作用

要在一定时间后停止对某些请求获取
ETIMEDOUT
ESOCKETTIMEDOUT
,请执行以下操作:

  • 不要在循环中的每个请求上配置
    request
    设置。相反,在循环之前只使用设置创建一次
    请求
    包装。作为缔约国:
  • 请注意,如果在循环中发送多个请求并创建 多个新池对象,maxSockets将无法按预期工作。到 解决这个问题,可以使用request.defaults和池选项 或者创建池对象,其maxSockets属性位于 循环

  • 然而,即使在实现该功能并使用
    {maxSockets:Infinity}
    配置池时,我仍然面临错误解决我问题的唯一配置是
    永远:true
    。这将使已建立的连接保持活动状态
  • 因此,最后我的代码是这样的:

    const request=require('request');
    //定制包装
    const customRequest=request.defaults({
    永远:真的,
    超时:20000,
    编码:空
    })
    循环(url,(url)=>{//对于我的每个url
    customRequest({uri:url},(err,res,body)=>{
    控制台日志(“完成”);
    });
    });
    

    使用这种策略,我能够以每秒25个请求的速度处理大约400K个请求,而在处理过程中没有任何问题(Ubuntu 18.04 VM,4GB RAM,默认UV_线程池大小)。

    为什么池(请求时)设置两次?这是为了禁用池。无论有没有池和maxSockets,我仍然会出现错误。您能找到原因吗?请参阅我的答案以获得解决方案:我也有同样的问题,但此解决方案不适用于我。有什么想法吗?这意味着要么问题在别处,要么你正在耗尽你的128个线程。在后一种情况下,您需要以本机方式进行DNS解析——避免
    getaddrinfo(3)
    #!/usr/bin/env node
    process.env.UV_THREADPOOL_SIZE = 128;
    
    function main() {
       ...
    }
    
    var pool = new https.Agent({ keepAlive: true });
    
    function getJsonOptions(_url) {
        return {
            url: _url,
            method: 'GET',
            agent: pool,
            json: true
        };
    }