草庐IT

javascript - node.js/Express在高负载下抛出 'RangeError: Maximum call stack size exceeded'

coder 2023-05-29 原文

我们的节点环境在高压下运行时遇到问题
我们无法找到来源的负载。

一点背景:我们正在使用以下命令运行集群节点应用程序
表达为http框架。目前,有3个盒子,每个盒子8个
每个CPU核心,每个机箱运行6个节点的集群
工作人员。该设置似乎工作得很好,我已经研究了所有
建议的方法,这样我相信设置是可靠的。是
使用Express 2.5.11和XMLHttpRequest 1.4.2运行node.js 0.8.1

问题来了:我们正在对该产品进行“黑暗发射”测试
(即,浏览器客户端代码中有对我们API的javascript ajax调用,
背景,但未在页面上使用或未显示给用户)。成功运行几分钟后,系统将抛出:

[RangeError: Maximum call stack size exceeded]

我们正在通过“uncaughtException”事件捕获错误
群集 Controller (启动每个工作程序),但是没有
在该级别可用的堆栈跟踪。我已经对
这个问题,似乎找不到任何有类似错误的人。后
梳理系统中的每一行代码,这就是我所知道的:
  • 我找不到任何递归或循环引用。 (我读过
    这个错误并不总是意味着递归问题,但是我们已经检查过了;
    我们实际上还是通过删除大部分代码来运行测试,
    仍然发生,请参阅下文);
  • 我已经降低到每个框1个工作进程,以尝试消除
    集群问题-问题仍然存在;
  • 该问题仅在高负载下发生。我们的流量约为。
    每秒1500页,在交通繁忙时,可达到15000页
    每秒页面数(我们无法在开发人员上复制
    环境);
  • 捕获错误的时间有所不同,但通常在15分钟以内。
  • 该错误似乎对操作没有影响!我的意思是
    没有腐败 react ,除了偶尔的超时,
    系统永不崩溃;
  • 捕获错误的工作进程将恢复并开始提供服务
    几秒钟后再次请求;
  • 我已经在最基本的设计上发生了错误-否
    会调用其他API。只需提出要求,然后回复
    简单的json响应。这是最奇怪的部分。好像没
    就像系统在我的任何代码中都失败了-没有
    实例化任何类以完成实际工作。显然,我
    从更多的代码开始,但慢慢地取出片段,直到
    在基本设置下仍然失败。

  • 我认为,最有说服力的症状是该错误总是会发生
    完全满足请求后。也就是说,服务器需要一个
    请求,找到正确的Express路由,调用res.send,然后
    完成的。对我来说,这真像是垃圾回收!我读了
    V8引擎具有非常好的GC引擎,但我想知道如何
    我们沉重的负担正在影响事物。

    如我所说,即使在基本设计上,代码也会引发错误。有
    删除了大部分的自定义代码,这是设置的基础。
    抱歉,我在这里剪切,所以并不是所有的变量声明都可以
    被包括在内,但是代码确实起作用,并且所有这些东西都在其中
    真实代码:

    集群 Controller 。这是从命令行启动的内容的清理版本。
    cluster = require('cluster');
    path = require('path');
    fs = require('fs');
    app = require('./nodeApi');
    _ = require('underscore');
    nodeUtil = require(./nodeUtil);
    
    process.on('uncaughtException', function(err) {
      var stamp;
      stamp = new Date();
      console.log("***************************** Exception Caught, " + stamp);
      return console.log("Exception is:", err);
    });
    
    if (cluster.isMaster) {
      if ((nodeUtil.isLiveServer() || nodeUtil.isCluster()) && process.env.IS_CLUSTER !== '0') {
        numCPUs = require("os").cpus().length - 2;
        if (numCPUs <= 0) {
          numCPUs = 1;
        }
      } else {
        numCPUs = 1;
      }
      console.log("Forking " + numCPUs + " workers...");
      for (i = _i = 1; 1 <= numCPUs ? _i <= numCPUs : _i >= numCPUs; i = 1 <= numCPUs ? ++_i : --_i) {
        worker = cluster.fork();
      }
    } else {
      app.start();
    }
    

    nodeWorker代码。 使用Express和一条简单的路线即可
    要求。如果使用jsonp,请求将包装在回调中(对于我们
    用ajax测试,这是必需的)
    (function() {
      var crypto, express, fs, modroot, path, staticroot, _;
      express = require('express');
      _ = require('underscore');
      fs = require('fs');
      path = require('path');
    
      module.exports.start = function() {
        logFile = fs.createWriteStream("" + logpath + "/access.log", {
          flags: 'a'
        });
    
        app = express.createServer();
    
        app.configure(function() {
          app.use(express.logger({
            stream: logFile,
            format: ':remote-addr - [:date] - ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" :response-time ms'
          }));
          app.use(express.errorHandler({
            dumpExceptions: true,
            showStack: true
          }));
          app.use(express.cookieParser());
          app.use(express.bodyParser());
          app.use(express.session({
            secret: "ourMemStoreSecret",
            cookie: {
              domain: ".ourdomain.com"
            },
            maxAge: new Date(Date.now() + 7200000),
            // The store WAS a redis store.  I took it out to eliminate redis as the issue.  We don't use sessions anyway.
            store: new require('express').session.MemoryStore({
              reapInterval: 60000 * 15
            })
          }));
          app.use(express["static"](staticroot));
          app.set('view engine', 'underscore');  // For our template rendering.  Not used in this test.
          app.set('views', __dirname + '/views/src');
          app.set('view options', {
            layout: false
          });
          app.use(app.router);
        });
    
        ignore = function(req, res, next) {
          if (req.params.api === 'favicon.ico') {
            return next('route');
          }
          return next();
        };
    
        wrapCallback = function(req, res, next) {
          var callbackName;
          if (callbackName = req.query.callback) {
            req.wrapCallback = true;
            res._send = res.send;
            res.send = function(data, status) {
              var dataString;
              if (_.isObject(data)) {
                dataString = encodeURI(JSON.stringify(data));
                res.setHeader('Content-Type', 'application/javascript');
                return res._send("" + callbackName + "(\"" + dataString + "\")", status);
              } else {
                data = encodeURI(data);
                return res._send("" + callbackName + "(\"" + data + "\")", status);
              }
            };
          }
          return next();
        };
    
        app.error(function(err, req, res, next) {
          console.log("[" + process.pid + "] Error Handler. Ok.", err);
          return res.send({
            error: err.msg
          }, err.statusCode);
        });
    
        // Does anyone know how to hard-code a path AND put it into a variable at the same time?
        // Kind of like: "/:api=MyTestAPI"  ??  That's why this route is here.
        setAPIName = function(req, res, next) {
          req.params.api = 'MyTestAPI';
          return next();
        };
        app.get("/MyTestAPI", setAPIName, wrapCallback, function(req, res) {
          res.send({
            hello: 'world'
          }, 200);
          return console.log("[" + process.pid + "] res.send (no cacher) is done");
        });
    
        process.setMaxListeners(0);
        process.send({
          // For IPC - the controller has a handler for this message
          cmd: 'isStarted'
        });
        return app.listen(process.env.APP_PORT);
      };
    
    }).call(this);
    

    错误的外观。 基本上,我从未见过
    请求的中间。没有错误的调用堆栈
    要么-这只是堆栈溢出消息。在这里你可以看到2
    工作进程处理提供响应的每个进程,然后出现以下错误之一
    他们。
    [660] res.send (no cacher) is done
    [654] res.send (no cacher) is done
    ***************************** Exception Caught, Fri Nov 02 2012 10:23:48 GMT-0400 (EDT)
    

    我真的很感谢对此的一些反馈。系统运行
    精美,并能够处理3箱我们巨大的交通。
    盒子上的负载约为40%,而且嗡嗡作响。我很想找到
    这个问题的根源,以便其他人可以像我一样为这个系统感到骄傲,
    并向node.js非信徒展示这是一个了不起的产品!

    最佳答案

    在我的一个生产环境中,我遇到了同样的问题。在分析过程中,我发现以下问题,可能是我错了。但是我希望这会对您有所帮助...

    此问题基本上与Socket有关。有一个选项应该接受多少个开放的Socket连接?并可以保持半开状态吗?

    通常,发生这种异常仅是因为您在特定时间段内打服务器的频率很高。

    让我清楚地解释一下...

  • 假设只有两个套接字路径,并且您有四个请求,每个请求都需要5秒钟的处理时间。
  • 通常,当您在第0秒发出2个请求并在第6秒剩下2个请求时,NodeJ可以完美地服务。
  • 而不是这样,如果您在第0秒发出4个请求,则NodeJ仅准备服务2个请求。 NodeJ只是关闭其余两个请求的套接字。
    注意:稍后,如果您发出相同的请求,NodeJ将接受并给出响应。
  • 有关更多信息,请通过socket.io.js实现。

  • 我的解决方案是
  • 以服务器友好的方式创建负载均衡器。
  • 在负载均衡器下运行NodeJs实例或集群。

  • 或者,如果您找到其他简单的方法来解决此问题,请更新此帖子...

    我正在等待知道这个问题的一个很好的解决方案。

    谢谢

    关于javascript - node.js/Express在高负载下抛出 'RangeError: Maximum call stack size exceeded',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13201667/

    有关javascript - node.js/Express在高负载下抛出 'RangeError: Maximum call stack size exceeded'的更多相关文章

    1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    3. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

      我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

    4. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

      在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

    5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

      我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

    6. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

      我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

    7. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

      我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

    8. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

    9. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

      似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

    10. ruby-on-rails - Rails - 使用/自定义 URL : '/dashboard' 指定根路径 - 2

      如何使此根路径转到:“/dashboard”而不仅仅是http://example.com?root:to=>'dashboard#index',:constraints=>lambda{|req|!req.session[:user_id].blank?} 最佳答案 您可以通过以下方式实现:root:to=>redirect('/dashboard')match'/dashboard',:to=>"dashboard#index",:constraints=>lambda{|req|!req.session[:user_id].b

    随机推荐