node和socket.io多次API调用会在一段时间后挂起

时间:2018-02-20 00:09:03

标签: node.js express socket.io

我有一个节点快速/套接字应用程序,其中我的快速服务器进行多次API调用,其中node-rest-client循环遍历var作业中的元素,当每次完成时,它通过套接字io将数据发送到客户端。但是,在大约1000个API调用之后,我偶尔会遇到套接字挂起错误。

events.js:182
      throw er; // Unhandled 'error' event
      ^

Error: socket hang up
    at createHangUpError (_http_client.js:345:15)
    at Socket.socketOnEnd (_http_client.js:437:23)
    at emitNone (events.js:110:20)
    at Socket.emit (events.js:207:7)
    at endReadableNT (_stream_readable.js:1059:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

您如何处理这些错误?或许我最初尝试编写此函数的代码很糟糕,在这种情况下,有关如何进行多个API调用并将结果发送到所有套接字的任何建议都会连接? (要求,我获取信息的唯一方法是通过进行这些API调用)。

服务器:

setInterval(function(){
  var jobs = ['J1', 'J2', 'J3', 'J4'];
  var full_data = {};
  for(var i = 0; i < jobs.length; i++){
    client.get("MY URL", function (data, response) {
        io.sockets.emit('progressbar', data);
      });
  }
  console.log(full_data);

}, 5000)

其中,&#39;进度条&#39;是监听数据的客户端功能。

2 个答案:

答案 0 :(得分:1)

如果您的jobs数组变大,那么您可能同时在飞行中有太多请求。它可能是:

  1. 因为本地耗尽了套接字资源
  2. 你重载你正在发出请求的主机,并且它处理来自一个来源的太多请求的方式就是挂断(这是最可能的解释,与你得到的错误相匹配)。
  3. 完成所有请求所需的时间超过5秒,因此您需要在上一次迭代完成之前开始下一次迭代。
  4. 我建议使用以下解决方案来处理所有这些问题:

    const Promise = require('bluebird');
    const utils = require('utils');
    client.getAsync = utils.promisify(client.get);
    
    function runJobs() {
        var jobs = ['J1', 'J2', 'J3', 'J4'];
        var full_data = {};
        Promise.map(jobs, function(job) {
            return client.getAsync("MY URL").then(data => {
                io.emit('progressbar', data);
            }).catch(err => {
                console.log('something went wrong on the request', err.request.options);
                // eat the error on purpose to keep going
            });
        }, {concurrency: 5}).then(() => {
            // All done, process all final data here            
            // Then, schedule the next iteration
            setTimeout(runJobs, 5000);
        });
    }
    
    runJobs();
    

    一次最多可以运行5个请求(您可以调整该数字),这可以解决上面的第1项和第2项。并且,它使用循环setInterval()而不是setTimeout(),因此它不会安排下一次迭代,直到完成前一次迭代(即使目标服务器变得非常慢)。

答案 1 :(得分:0)

结果是导致错误的client.get()请求。这是我的代码来解决这个问题。它仍然是错误,但至少处理错误并且不会导致节点服务器崩溃。如果有更有说服力的处理方式,请告诉我!

setInterval(function(){
  var jobs = ['J1', 'J2', 'J3', 'J4'];
  var full_data = {};
  for(var i = 0; i < jobs.length; i++){
    client.get("MY URL", function (data, response) {
        io.sockets.emit('progressbar', data);
      }).on('error', function (err) {
        console.log('something went wrong on the request', err.request.options);
    });
  }
  console.log(full_data);

}, 5000)