熱門分類
載入中…
目錄0%

🚀 Linux 效能調優:針對高併發 Nginx 環境的 Sysctl 核心參數優化全紀錄

    🚀 Linux 效能調優:針對高併發 Nginx 環境的 Sysctl 核心參數優化全紀錄


    一、這篇在解決什麼問題?(高併發 Nginx 的典型瓶頸)

    Nginx 本身很能扛,但「扛得住」不代表「扛得漂亮」。高併發下常見卡點不在 Nginx,而在 Linux 核心的資源上限與 TCP/IP 佇列:

    • 連線佇列太小:accept queue / SYN backlog 撐不住,出現丟包、重傳、握手延遲。
    • TIME_WAIT/短連線壓力:大量短連線造成 port、socket、記憶體與回收壓力。
    • socket buffer 不夠:吞吐上不去、延遲抖動、尖峰時更明顯。
    • 檔案描述符不夠:直接噴 Too many open files 或隱性掉連線。
    • NIC/backlog 緩衝不足:封包一多就排隊、drop。

    二、先建立「基準」:不要一上來就亂改

    建議先把現況抓下來,後面調整才知道改了什麼、有效沒效。

    # 1) 核心版本 / CPU / 記憶體 / NIC
    uname -a
    lscpu
    free -h
    ip -s link
    
    # 2) 目前 sysctl(抓重點即可)
    sysctl net.core.somaxconn
    sysctl net.core.netdev_max_backlog
    sysctl net.ipv4.tcp_max_syn_backlog
    sysctl net.ipv4.ip_local_port_range
    sysctl net.ipv4.tcp_fin_timeout
    sysctl net.ipv4.tcp_tw_reuse
    sysctl net.ipv4.tcp_keepalive_time
    sysctl net.ipv4.tcp_congestion_control
    sysctl net.ipv4.tcp_fastopen
    
    # 3) 連線與 socket 概況(尖峰時最好也抓一次)
    ss -s
    cat /proc/net/sockstat
    cat /proc/net/sockstat6
    
    # 4) Nginx process 檔案上限(很重要)
    pidof nginx | tr ' ' '\n' | head -n 1 | xargs -I{} cat /proc/{}/limits | grep -i "Max open files"

    三、推薦 Sysctl 配置(高併發 Web / Reverse Proxy 常用組合)

    以下提供一份「偏保守、可用於多數高併發 Nginx」的起手式。不是越大越好,而是要跟你的流量型態(長連線/短連線)、上游服務、以及 NIC 能力匹配。

    # 建議建立獨立檔案,便於控版與回滾
    sudo tee /etc/sysctl.d/99-nginx-highconcurrency.conf > /dev/null <<'EOF'
    # =========================================================
    # Nginx High Concurrency Sysctl Tuning
    # 目的:提升佇列承載、降低尖峰 drop、改善短連線壓力
    # 注意:套用前請先建立基準並準備回滾
    # =========================================================
    
    # --- 1) 連線佇列 / 網卡 backlog ---
    net.core.somaxconn = 4096
    net.core.netdev_max_backlog = 16384
    
    # --- 2) TCP 握手 / SYN backlog(半連線)---
    net.ipv4.tcp_max_syn_backlog = 8192
    net.ipv4.tcp_syncookies = 1
    
    # --- 3) ephemeral ports(大量短連線、反向代理特別常見)---
    net.ipv4.ip_local_port_range = 10240 65535
    
    # --- 4) TIME_WAIT / 連線回收(保守設定:不把它當魔法)---
    # tcp_tw_reuse:偏向 client-side,大量短連線時可能有助,但不是通用解法
    net.ipv4.tcp_tw_reuse = 0
    net.ipv4.tcp_fin_timeout = 30
    
    # --- 5) keepalive(避免死連線佔資源;依服務型態調整)---
    net.ipv4.tcp_keepalive_time = 600
    net.ipv4.tcp_keepalive_intvl = 30
    net.ipv4.tcp_keepalive_probes = 5
    
    # --- 6) socket buffer(吞吐與延遲的基礎盤;不要無腦拉爆)---
    net.core.rmem_max = 134217728
    net.core.wmem_max = 134217728
    net.ipv4.tcp_rmem = 4096 1048576 134217728
    net.ipv4.tcp_wmem = 4096 1048576 134217728
    
    # --- 7) 其他常見穩定項(維持預設即可,也可明確寫出)---
    net.ipv4.tcp_timestamps = 1
    net.ipv4.tcp_sack = 1
    net.ipv4.tcp_window_scaling = 1
    
    # --- 8) FQ + BBR(若核心與發行版支援,可考慮;不強制)---
    # net.core.default_qdisc = fq
    # net.ipv4.tcp_congestion_control = bbr
    
    # --- 9) 檔案描述符(系統層上限;仍需配合 systemd / nginx 設定)---
    fs.file-max = 2097152
    EOF
    
    # 套用
    sudo sysctl --system
    
    # 驗證
    sysctl net.core.somaxconn
    sysctl net.ipv4.tcp_max_syn_backlog
    sysctl net.ipv4.ip_local_port_range

    四、每個參數到底在調什麼?(白話但不含糊)

    1) net.core.somaxconn:accept queue 上限

    當連線完成三向交握後,會進入等待 accept() 的佇列。這個佇列太小,高峰就會排不進去。Nginx 的 listen backlog 不應高於 somaxconn,否則也會被截斷。

    2) net.ipv4.tcp_max_syn_backlog:SYN backlog(半連線上限)

    握手未完成前的半連線佇列。尖峰或遇到 SYN flood 時,這裡太小就容易掉握手。tcp_syncookies=1 可作為壓力保護,但不建議把它當作長期依賴,仍要搭配合理的佇列與防護。

    3) net.core.netdev_max_backlog:NIC 收包到 CPU 前的緩衝

    網卡進來的封包,CPU 忙時會先排隊。這裡偏小就容易 drop,尖峰抖動會變大。常見做法是配合中斷綁核、RPS/RFS、以及 NIC ring buffer 一起看,但這篇先聚焦 sysctl。

    4) net.ipv4.ip_local_port_range:本機臨時 port 範圍

    反向代理/上游連線多時,Nginx 會對上游建立大量本機連線,會耗掉 ephemeral ports。範圍太窄會出現「連線突然上不去」或偶發錯誤。把範圍拉大通常是低風險高收益的一步。

    5) tcp_fin_timeout / tcp_tw_reuse:短連線的地雷區

    很多人看到 TIME_WAIT 就想「消滅它」,但 TIME_WAIT 是 TCP 正常機制的一部分。
    本篇採保守策略:先不把 tcp_tw_reuse 當成通用解法,只做有限的回收速度調整(例如 tcp_fin_timeout)。如果你的情境是「大量 client-side 短連線」或「loopback 封包」等特殊案例,再另外做 A/B 驗證會比較安全。

    6) socket buffer:吞吐的底座,但也可能吃光記憶體

    rmem/wmem 拉高,有助於高吞吐、長 RTT 或突發流量,但也會增加記憶體壓力。建議用監控看 socket memory、TCP retrans、以及 p99 latency,再逐步調整,不要一次拉到誇張。


    五、不要只調 Sysctl:Nginx 與 systemd 必須同步

    Sysctl 把「道路拓寬」了,但 Nginx 這台車如果限速(nofile / worker_connections)沒解開,效果會直接被卡死。

    1) systemd:提升 Nginx 服務的 nofile 上限

    # 建立 override(不同發行版 nginx.service 位置不同,但做法一致)
    sudo systemctl edit nginx.service
    
    # 加上:
    # [Service]
    # LimitNOFILE=1048576
    
    sudo systemctl daemon-reload
    sudo systemctl restart nginx
    
    # 驗證
    pidof nginx | tr ' ' '\n' | head -n 1 | xargs -I{} cat /proc/{}/limits | grep -i "Max open files"

    2) Nginx:worker 連線與檔案描述符

    # /etc/nginx/nginx.conf(示意)
    worker_processes auto;
    worker_rlimit_nofile 1048576;
    
    events {
      worker_connections  65535;
      multi_accept on;
      use epoll;
    }
    
    # 若你有明確高峰排隊問題,可考慮明確指定 backlog(需與 somaxconn 對齊)
    # server {
    #   listen 443 ssl http2 backlog=4096;
    # }

    六、驗證是否真的「變快了」:看這些就夠用

    調校成功通常不是「CPU 降很多」這麼直覺,而是尖峰掉包下降、握手更穩、p95/p99 latency 收斂、連線錯誤下降。

    # 1) 連線總覽
    ss -s
    
    # 2) SYN / listen overflow / drop(有些計數可從內核統計觀察)
    netstat -s | egrep -i "listen|overflow|drop|retrans|syn"
    
    # 3) socket 資源
    cat /proc/net/sockstat
    cat /proc/net/sockstat6
    
    # 4) Nginx 狀態(若你有啟用 stub_status)
    # curl -s http://127.0.0.1/nginx_status
    
    # 5) 壓測(範例:請依你環境挑工具)
    # wrk -t8 -c2000 -d60s https://your-domain/
    # hey -z 60s -c 2000 https://your-domain/

    七、回滾策略(一定要先準備)

    一旦發現異常(例如連線行為改變、上游 timeout、p99 變差),回滾要能在 1 分鐘內完成。

    # 1) 直接移除配置檔並重載 sysctl
    sudo mv /etc/sysctl.d/99-nginx-highconcurrency.conf /root/99-nginx-highconcurrency.conf.bak
    sudo sysctl --system
    
    # 2) 或只回退單一參數(立即生效但不持久)
    sudo sysctl -w net.core.somaxconn=128
    
    # 3) 確認值
    sysctl net.core.somaxconn

    八、常見陷阱與務實建議

    • 「值越大越好」是錯的:佇列與 buffer 會吃資源,尖峰好看、常態變慢也不意外。
    • TIME_WAIT 不等於問題:它常是「你真的很忙」的副作用;先確認是否是短連線過多、Keep-Alive 設計不合理。
    • 反向代理要看 ephemeral ports:上游連線多時,ip_local_port_range 往往比你想得更重要。
    • Gateway、DNS、上游 RTT:網路路徑(Gateway)、DNS 回應與上游延遲,常常才是 p99 的真正兇手,別只盯 sysctl。
    • 最有效的方式:先建立基準 → 小步改動 → 看指標 → 再決定要不要放大。

    💬 你目前的高併發瓶頸是哪一種?
    • 握手尖峰:SYN backlog / accept queue overflow?
    • 短連線:TIME_WAIT 太多、ephemeral ports 不夠?
    • 吞吐:socket buffer、retrans、p99 latency 抖動?

    你可以在留言貼上 ss -snetstat -s 的關鍵片段(遮蔽網域/IP 即可),我會用「可回滾」的方式幫你把調校路線收斂到最少改動、最大收益。

    延伸閱讀

    🔗 分享這篇 LINE Facebook X

    沒有留言:

    字級