Nginx

Nginx 在 Debian10 而不是 Debian9 的高負載下失敗

  • May 9, 2021

nginx 從來沒有出現過任何問題。我們在很多 Spring Boot 應用伺服器前面使用 5 台 Nginx 伺服器作為負載均衡器。

我們多年來一直在 debian 9 上使用預設的 nginx 包 1.10.3 執行它們。現在我們將三個負載均衡器切換到帶有 nginx 1.14.2 的 debian 10。首先,一切順利。然後,在高負載下,我們遇到了一些問題。它開始於

2020/02/01 17:10:55 [crit] 5901#5901: *3325390 SSL_write() failed while sending to client, client: ...
2020/02/01 17:10:55 [crit] 5901#5901: *3306981 SSL_write() failed while sending to client, client: ...

在這之間我們得到很多

2020/02/01 17:11:04 [error] 5902#5902: *3318748 upstream timed out (110: Connection timed out) while connecting to upstream, ...
2020/02/01 17:11:04 [crit] 5902#5902: *3305656 SSL_write() failed while sending response to client, client: ...
2020/02/01 17:11:30 [error] 5911#5911: unexpected response for ocsp.int-x3.letsencrypt.org

它以

2020/02/01 17:11:33 [error] 5952#5952: unexpected response for ocsp.int-x3.letsencrypt.org

該問題僅在高負載下退出 30-120 秒,然後消失。

在核心日誌中,我們有時有:Feb 1 17:11:04 kt104 kernel:

$$ 1033003.285044 $$TCP:request_sock_TCP:埠 443 上可能的 SYN 泛洪。發送 cookie。檢查 SNMP 計數器。 但在其他情況下,我們看不到任何 kernel.log 消息

在 debian 9 和 debian 10 伺服器上,我們使用相同的設置並進行了一些 TCP 調整:

# Kernel tuning settings
# https://www.nginx.com/blog/tuning-nginx/
net.core.rmem_max=26214400
net.core.wmem_max=26214400
net.ipv4.tcp_rmem=4096 524288 26214400
net.ipv4.tcp_wmem=4096 524288 26214400
net.core.somaxconn=1000
net.core.netdev_max_backlog=5000
net.ipv4.tcp_max_syn_backlog=10000
net.ipv4.ip_local_port_range=16000 61000
net.ipv4.tcp_max_tw_buckets=2000000
net.ipv4.tcp_fin_timeout=30
net.core.optmem_max=20480

nginx的配置完全一樣,所以我只顯示主文件:

user www-data;
worker_processes auto;
worker_rlimit_nofile 50000;
pid /run/nginx.pid;

events {
   worker_connections 5000;
   multi_accept on;
   use epoll;
}

http {
   root /var/www/loadbalancer;
   sendfile on;
   tcp_nopush on;
   tcp_nodelay on;
   types_hash_max_size 2048;
   server_tokens off;
   client_max_body_size 5m;
   client_header_timeout 20s; # default 60s
   client_body_timeout 20s; # default 60s
   send_timeout 20s; # default 60s

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

   ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
   ssl_session_timeout 1d;
   ssl_session_cache shared:SSL:100m;
   ssl_buffer_size 4k;
   ssl_dhparam /etc/nginx/dhparam.pem;
   ssl_prefer_server_ciphers on;
   ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';

   ssl_session_tickets on;
   ssl_session_ticket_key /etc/nginx/ssl_session_ticket.key;
   ssl_session_ticket_key /etc/nginx/ssl_session_ticket_old.key;

   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_trusted_certificate /etc/ssl/rapidssl/intermediate-root.pem;

   resolver 8.8.8.8;

   log_format custom '$host $server_port $request_time $upstream_response_time $remote_addr "$ssl_session_reused" $upstream_addr $time_iso8601 "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent";

   access_log /var/log/nginx/access.log custom;
   error_log /var/log/nginx/error.log;

   proxy_set_header Host $http_host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_path /var/cache/nginx/ levels=1:2 keys_zone=imagecache:10m     inactive=7d use_temp_path=off;
   proxy_connect_timeout 10s;
   proxy_read_timeout 20s;
   proxy_send_timeout 20s;
   proxy_next_upstream off;

   map $http_user_agent $outdated {
   default 0;
   "~MSIE [1-6]\." 1;
   "~Mozilla.*Firefox/[1-9]\." 1;
   "~Opera.*Version/[0-9]\." 1;
   "~Chrome/[0-9]\." 1;
 }

 include sites/*.conf;
}

上游超時表明我們的 java 機器存在一些問題。但與此同時,debian9 nginx/loadbalancer 執行良好,連接到任何上游伺服器都沒有問題。letencrypt 和 SSL_write 的問題向我發出了 nginx 或 TCP 或其他問題的信號。我真的不知道如何調試這種情況。但我們可以可靠地重現它,大多數時候我們在 debian10 伺服器上遇到高負載並且在 debian 9 上從未見過它。

然後我在 debian10 上安裝了穩定版 nginx 1.16 看看這是否是 nginx 中已經修復的 bug:

nginx version: nginx/1.16.1
built by gcc 8.3.0 (Debian 8.3.0-6)
built with OpenSSL 1.1.1c 28 May 2019 (running with OpenSSL 1.1.1d 10 Sep 2019)
TLS SNI support enabled
configure arguments: ...

但這沒有幫助。

這似乎是一個與網路相關的問題。但是我們不會在應用程序伺服器上遇到它。但負載當然較低,因為負載均衡器/nginx 機器必須處理外部和內部流量。

調試非常困難,因為它只發生在高負載時。我們嘗試使用 ab 對伺服器進行負載測試,但我們無法重現該問題。

有人可以幫助我並給我一些提示如何開始進一步調試這種情況嗎?

accept_mutex 在預設值中從 on 更改為 off。將其重新設置為“on”,Nginx 再次以每秒 10k 個請求的速度愉快地執行。我想這是 multi_accept 和 accept_mutex 的組合導致了我的麻煩。

順便說一下,我們不推薦這些設置,我們通過重用埠等更改為更現代的設置。請按照 Nginx 部落格上的指南進行自己的設置。Nginx 很棒。

引用自:https://serverfault.com/questions/1002021