【问题标题】:Why increasing worker_connections in Nginx makes the application slower in node.js cluster?为什么在 Nginx 中增加 worker_connections 会使 node.js 集群中的应用程序变慢?
【发布时间】:2016-03-22 07:26:25
【问题描述】:

我正在将我的应用程序转换为 node.js 集群,我希望它可以提高我的应用程序的性能。

目前,我正在将应用程序部署到 2 个 EC2 t2.medium 实例。我有 Nginx 作为代理和 ELB。

这是我的快速集群应用程序,它在文档中非常标准。

var bodyParser = require('body-parser');
var cors = require('cors');
var cluster = require('cluster');
var debug = require('debug')('expressapp');

if(cluster.isMaster) {
  var numWorkers = require('os').cpus().length;
  debug('Master cluster setting up ' + numWorkers + ' workers');

  for(var i = 0; i < numWorkers; i++) {
    cluster.fork();
  }

  cluster.on('online', function(worker) {
    debug('Worker ' + worker.process.pid + ' is online');
  });

  cluster.on('exit', function(worker, code, signal) {
    debug('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
    debug('Starting a new worker');
    cluster.fork();  
  });
} else {
  // Express stuff
}

这是我的 Nginx 配置。

nginx::worker_processes: "%{::processorcount}"
nginx::worker_connections: '1024'
nginx::keepalive_timeout: '65'

我在 Nginx 服务器上有 2 个 CPU。

这是我之前的表演。

我得到 1,500 个请求/秒,这非常好。现在我想我会增加 Nginx 上的连接数,以便我可以接受更多请求。我这样做。

nginx::worker_processes: "%{::processorcount}"
nginx::worker_connections: '2048'
nginx::keepalive_timeout: '65'

这是我的表演后。

我认为这比以前更糟。

我使用 gatling 进行性能测试,代码如下。

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class LoadTestSparrowCapture extends Simulation {
  val httpConf = http
    .baseURL("http://ELB")
    .acceptHeader("application/json")
    .doNotTrackHeader("1")
    .acceptLanguageHeader("en-US,en;q=0.5")
    .acceptEncodingHeader("gzip, defalt")
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0")

    val headers_10 = Map("Content-Type" -> "application/json")

    val scn = scenario("Load Test")
      .exec(http("request_1")
        .get("/track"))

    setUp(
      scn.inject(
        atOnceUsers(15000)
      ).protocols(httpConf))
}

我将它部署到我的 gatling 集群。因此,我有 3 个 EC2 实例在 30 秒内向我的应用程序发出 15,000 个请求。

问题是,我可以做些什么来提高我的应用程序的性能,或者我只需要添加更多机器?

我正在测试的路由非常简单,我收到请求并将其发送到 RabbitMQ,以便进一步处理它。因此,该路线的响应非常快。

【问题讨论】:

  • 您的失败请求较少。怎么可能更糟?你有多少并发连接?我的猜测是,在第一种情况下你用完了 worker_connections,而在第二种情况下你用完了节点的应用程序功能。
  • 我查看了每秒的请求数,我认为这是因为我的应用程序速度较慢,因此无法接受很多连接?
  • 性能是一件复杂的事情。假设您的应用程序可以在 10 毫秒内响应。这意味着它每秒可以处理大约 100 个请求。但是如果你一次发送 200 个请求,其中一些将不得不等待将近 2 秒,这意味着他们将使用更多的连接等等......

标签: javascript node.js performance nginx gatling


【解决方案1】:

您提到您正在使用 AWS 并在 ELB 中的 EC2 实例的前面。如我所见,您将获得 502 和 503 状态代码。这些可以从 ELB 或您的 EC2 实例发送。确保在进行负载测试时您知道错误来自何处。您可以在 ELB CloudWatch metrics 的 AWS 控制台中检查这一点。

基本上HTTPCode_ELB_5XX 表示您的 ELB 发送了 50 倍。另一方面,HTTPCode_Backend_5XX 发送了 50x。 您也可以在 ELB 的日志中验证这一点。关于 ELB 错误的更好解释你可以找到here

要在 AWS 上进行负载测试,您绝对应该阅读 this。关键是 ELB 只是另一组机器,如果你的负载增加,它需要扩展。默认扩展策略是(引自“加速测试”部分):

一旦您有了测试工具,您就需要定义负载的增长。我们建议您以每五分钟不超过 50% 的速度增加负载。

这意味着当您从一定数量的并发用户开始时,比如说 1000,默认情况下,您应该在 5 分钟内最多增加到 1500。这将保证 ELB 将随着服务器上的负载而扩展。确切的数字可能会有所不同,您必须自己测试它们。上次我测试了它的持续负载 1200 req./s w/o 一个问题,然后我开始收到 50x。您可以轻松地从单个客户端运行从 X 到 Y 用户的加速场景并等待 50 倍来测试它。

下一个非常重要的事情(来自“DNS 解析”部分)是:

如果客户端没有至少每分钟重新解析一次 DNS,则 Elastic Load Balancing 添加到 DNS 的新资源将不会被客户端使用。

简而言之,这意味着您必须保证 DNS 中的 TTL 受到尊重,或者您的客户端通过执行 DNS 查找来重新解析和轮换他们收到的 DNS IP,以保证以循环方式分配负载。如果不是(例如,仅从一个客户端进行测试,而不是您的情况),您可以通过将所有流量仅定位到一个实例来使 ELB 的一个实例超载来扭曲结果。这意味着 ELB 根本无法扩展。

希望它会有所帮助。

【讨论】:

    猜你喜欢
    • 2021-06-27
    • 2021-05-26
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2011-04-19
    • 2023-03-20
    • 2018-10-10
    • 2023-03-04
    相关资源
    最近更新 更多