【问题标题】:Why won't nginx accept more than 1024 connections from apache bench为什么 nginx 不接受来自 apache bench 的超过 1024 个连接
【发布时间】:2016-09-14 22:42:41
【问题描述】:

我有一个 clojure/jetty 服务器(在端口 8081 上)并使用 nginx 代理它(端口 8080)。我一直在尝试单独对 clojure 应用程序以及 nginx 以代理角色进行基准测试。

当我直接针对 clojure 运行测试时,我可能会得到 Connection reset by peer,十分之一的运行。一般来说,测试完成,性能可以接受。

$ ulimit -n 4096
$ ab -n 20000 -c 2048 -k localhost:8081
...
Concurrency Level:      2048
Time taken for tests:   8.713 seconds
Complete requests:      20000
Failed requests:        0
Keep-Alive requests:    20000
Total transferred:      15160000 bytes
HTML transferred:       11720000 bytes
Requests per second:    2295.43 [#/sec] (mean)
Time per request:       892.208 [ms] (mean)
Time per request:       0.436 [ms] (mean, across all concurrent requests)
Transfer rate:          1699.16 [Kbytes/sec] received
...

我开始测试完整的本地配置,8080 端口上的 nginx 和 8081 上的 clojure。一切顺利,直到我超过 1024 个并发连接。

我注意到,使用ss -tl,接收队列没有尖峰,或者至少如果它们是瞬间的。但我确实发现,使用netstat -s,正在发送大量 TCP RST。偶尔,dmesg 告诉我看起来好像有 SYN 洪水。此外,nginx 正在响应 HTTP 状态 499,这应该表示客户端关闭连接...

所以,我的诊断结果是交叉的,apache bench 和 nginx 都声称对方关闭了连接!?

$ ulimit -n 4096
$ ab -n 20000 -c 2048 -k localhost:8080
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
apr_socket_recv: Connection reset by peer (104)
Total of 26 requests completed

配置

我将 nginx 和 clojure 的 ulimit max open files 设置为 4096。

无效的网络更改

net.core.netdev_max_backlog=30000
# yes, we are using jumbo frames
net.ipv4.tcp_mtu_probing=1

net.core.somaxconn=4096
net.ipv4.ip_local_port_range=4096     61000
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_max_syn_backlog=2048

/etc/nginx/nginx.conf

user www-data;
worker_processes  2;
worker_rlimit_nofile 100000;

error_log  /var/log/nginx/error.log;
pid        /run/nginx.pid;

events {
  worker_connections  2048;
  use epoll;
}

http {

  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;


  access_log    /var/log/nginx/access.log;

  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;

  keepalive_requests 1000;
  keepalive_timeout  65;


  gzip  on;
  gzip_http_version 1.0;
  gzip_comp_level 2;
  gzip_proxied any;
  gzip_vary off;
  gzip_types text/plain text/css application/x-javascript text/xml application/xml application/rss+xml application/atom+xml text/javascript application/javascript application/json text/mathml;
  gzip_min_length  1000;
  gzip_disable     "MSIE [1-6]\.";


  variables_hash_max_size 1024;
  variables_hash_bucket_size 64;
  server_names_hash_bucket_size 128;
  types_hash_max_size 2048;
  types_hash_bucket_size 64;



  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

/etc/nginx/sites-enabled/ups

upstream ups {
  server localhost:8081 fail_timeout=0;
}


server {
  listen 8080 backlog=1024;

  server_name example.com;

  proxy_buffer_size   128k;
  proxy_buffers   4 256k;
  proxy_busy_buffers_size   256k;

  client_max_body_size 3M;

  large_client_header_buffers 4 128k;

  proxy_read_timeout 300;
  proxy_send_timeout 300;
  send_timeout 300;
  keepalive_timeout 300;

  server_tokens off;

  access_log /var/log/nginx/ups_access.log enhanced-combined;
  error_log /var/log/nginx/ups_error.log;
  root /apps/ups/current/public/;

  error_page 403 /errors/403_maintenance.html;
  error_page 500 /errors/500.html;
  location ^~ /errors/ {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Request-Id $request_uuid;
    satisfy any;
    allow all;
  }

  location / {

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Request-Id $request_uuid;

    if ($http_x_forwarded_proto = 'http') {
      rewrite ^ https://$host$request_uri? permanent;
    }


    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }

    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }

    if (!-f $request_filename) {
      proxy_pass http://ups;
      break;
    }
  }
}

【问题讨论】:

  • 尝试增加积压listen 8080 backlog=1024;
  • 第二个变种,尝试离开backlog=1024,将worker_processes更改为1并添加到events部分multi_accept on;accept_mutex off;
  • 我猜你应该增加 Worker 连接数
  • @Terra 我尝试了两种配置更改,结果相同
  • @AlexeyTen 我尝试将工作人员从 2 设置为 3,并从处理 24 个请求变为 1054,但最后我得到了同样的错误。我尝试了最多 4 个,但我仍然只处理了 1054 个请求。

标签: linux nginx tcp clojure benchmarking


【解决方案1】:

@Terra 几乎得到了最终解决的答案。

  • accept_mutex off;
  • worker_connections 4096;

我尝试单独添加每个更改并重新加载,但我仍然看到相同的错误。直到我改变了这两个,我才能超过 1024 个连接。

看来,由于代理,我需要有两倍于我打算接受的工作连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 2013-05-27
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    相关资源
    最近更新 更多