Home  >  Q&A  >  body text

javascript - nodejs爬网页的时候报错:(libuv) kqueue(): Too many open files in system

主要代码:

db_operation.db_getUrl('appsIndex_China', function(results){
    var arr = [],
        length = results.length;
    for(var i = 0; i < length; i++)
    {
        var item = results[i];
        (function(i, item){
            request(item.url, function(error, response, body){
                if(!error && response.statusCode == 200)
                {
                    $ = cheerio.load(body);
                    getAppDetail('#content', function(data){
                        data.id = item.id;
                        arr.push(data);
                        
                    });
                    if(arr.length == 100)
                    {
                        db_operation.db_addBasciDetail('appBasicDetail_China', arr);
                    }
                }    
            })
        }(i, item));
    }
})

length大概是1w6,应该是request的地址太多了,求问该怎么解决?跪谢!

baidu+google了一下,说要改系统最大打开的文件数,但是我现在能打开的文件数已经是1000000了:

黄舟黄舟2653 days ago394

reply all(1)I'll reply

  • ringa_lee

    ringa_lee2017-04-10 16:51:38

    1)OS能同时打开的文件数量有限制,即使你调大的系统值,也是有一个瓶颈的
    2)你要在代码中控制发送的异步请求的数量控制一定范围内,发送的过多实际上也没有意义,服务器发现同一个IP过来的请求数过多,也会拒绝你的请求

    你可以做如下修改试试:

    //全部请求完成后的回调函数
    function appsIndexChinaProcessDone(){
        
    }
    
    db_operation.db_getUrl('appsIndex_China', function(results){
        var arr = [],
            length = results.length;
        
        var correntRequest=1000;
        var finishedRequest=0;
        function processNext(){
            var item=results.shift();
            if(someData){
                request(item.url, function(error, response, body){
                    if(!error && response.statusCode == 200)
                    {
                        $ = cheerio.load(body);
                        getAppDetail('#content', function(data){
                            data.id = item.id;
                            arr.push(data);
    
                        });
                        if(arr.length == 100)
                        {
                            finishedRequest++;
                            db_operation.db_addBasciDetail('appBasicDetail_China', arr);
                        }
                        //也可以加在此时,只要回来200,不管有没有取到需要的数据
                        //finishedRequest++;
                    }else{
                        //放回队列中等待下次再尝试执行
                        //也可以不处理,看你的业务需求
                        results.push(item);
                    }
                    //获取下一个数据,发送请求
                    processNext();
                })
            }else{
                //因为异步请求,队列为空,不等于所有的请求处理完毕,需要判断时候完成的请求数量和实际要求的数量是否吻合
                if(finishedRequest===length){
                    console.log('process done!');
                    //全部执行完后执行回调,通知数据抓取完成
                    appsIndexChinaProcessDone();
                }
            }
            
        }
        
        //设置并发的初始请求数量,后续的请求通过processNext依次执行,一直到队列为空
        for(var i=0;i<correntRequest;i++){
            processNext();
        }
    });

    reply
    0
  • Cancelreply