上週線上服務扛不住流量,運維羣裏一頓排查,最後發現是內核參數沒調。
默認配置跑個開發環境還行,生產環境就是在給自己挖坑。
把這次調優過程記錄一下,都是踩過的坑。
背景
我們有台服務器,配置不差:
- 32核CPU
- 64G內存
- 萬兆網卡
但是一到高峯期,CPU才30%,連接數就上不去了,大量請求超時。
看了一圈監控,發現是網絡瓶頸,但網卡帶寬明明還有餘量。
問題定位
現象
# 查看連接狀態
ss -s
Total: 52341
TCP: 48234 (estab 12000, closed 35000, orphaned 0, timewait 34500)
# 發現大量TIME_WAIT
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
34523 TIME-WAIT
12034 ESTAB
1234 SYN-RECV
423 LISTEN
3萬多個TIME_WAIT,正常嗎?
短連接場景下其實很常見,但這麼多確實有問題。
根因分析
# 查看當前內核參數
sysctl net.ipv4.tcp_max_tw_buckets
# 輸出:net.ipv4.tcp_max_tw_buckets = 180000
sysctl net.core.somaxconn
# 輸出:net.core.somaxconn = 128
sysctl net.ipv4.tcp_max_syn_backlog
# 輸出:net.ipv4.tcp_max_syn_backlog = 1024
問題找到了:
somaxconn才128,這是監聽隊列的最大長度tcp_max_syn_backlog才1024,SYN隊列太小
高併發下,新連接進來排隊都排不下,直接被丟棄了。
調優方案
一、網絡連接相關
# /etc/sysctl.conf
# 1. 監聽隊列最大長度(默認128太小)
net.core.somaxconn = 65535
# 2. SYN隊列長度
net.ipv4.tcp_max_syn_backlog = 65535
# 3. 允許的最大跟蹤連接條目
net.netfilter.nf_conntrack_max = 1000000
# 4. TIME_WAIT狀態的socket數量(按需調整)
net.ipv4.tcp_max_tw_buckets = 200000
# 5. TIME_WAIT複用(僅限客户端發起連接時)
net.ipv4.tcp_tw_reuse = 1
# 6. 開啓SYN cookies防護
net.ipv4.tcp_syncookies = 1
# 7. 減少FIN_WAIT2狀態時間
net.ipv4.tcp_fin_timeout = 30
二、TCP緩衝區相關
# 接收緩衝區(最小、默認、最大)單位字節
net.ipv4.tcp_rmem = 4096 87380 16777216
# 發送緩衝區
net.ipv4.tcp_wmem = 4096 65536 16777216
# 系統級別的內存頁面分配
net.ipv4.tcp_mem = 786432 1048576 1572864
# 單個socket最大緩衝區
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
三、文件描述符相關
# 系統級最大文件描述符
fs.file-max = 1000000
# 單進程最大文件描述符(需要配合ulimit)
# 在 /etc/security/limits.conf 中設置:
# * soft nofile 1000000
# * hard nofile 1000000
四、應用生效
# 臨時生效
sysctl -p
# 驗證
sysctl net.core.somaxconn
# 輸出:net.core.somaxconn = 65535
調優前後對比
壓測數據
用wrk壓測同一個接口:
wrk -t12 -c1000 -d60s http://localhost:8080/api/test
調優前:
Requests/sec: 8234.56
Latency: avg 234ms, max 3.2s
Socket errors: connect 3421, read 234, write 0, timeout 523
調優後:
Requests/sec: 23456.78
Latency: avg 42ms, max 234ms
Socket errors: connect 0, read 0, write 0, timeout 0
QPS從8000提升到23000,延遲從234ms降到42ms,錯誤歸零。
生產環境表現
高峯期同樣流量:
- CPU使用率:從30%提升到65%(資源用起來了)
- 連接錯誤率:從5%降到0.01%
- P99延遲:從800ms降到120ms
常見場景參數模板
場景一:高併發Web服務
# 適合Nginx、Tomcat等Web服務器
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 3
# Nginx還需要改配置
# worker_connections 65535;
# 並且在listen後加 backlog=65535
場景二:數據庫服務器
# 適合MySQL、PostgreSQL等
# 內存相關(根據實際內存調整)
vm.swappiness = 10
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
# 文件系統
fs.file-max = 1000000
fs.aio-max-nr = 1048576
# 網絡(數據庫通常連接數不會太高但要穩定)
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
場景三:代理/網關服務
# 適合Nginx反向代理、API網關
# 代理需要大量連接,前端連接+後端連接
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# 端口範圍要大(代理會用很多端口連後端)
net.ipv4.ip_local_port_range = 1024 65535
# TIME_WAIT複用很重要
net.ipv4.tcp_tw_reuse = 1
# 連接跟蹤表要大
net.netfilter.nf_conntrack_max = 2000000
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
一些坑
坑1:改了不生效
# 檢查是否真的改了
sysctl -a | grep somaxconn
# 如果是容器環境,宿主機和容器的參數是隔離的
# 部分參數需要在宿主機改
坑2:Nginx的backlog
改了系統參數,Nginx也要配合改:
server {
listen 80 backlog=65535;
# ...
}
不然Nginx用的還是默認值511。
坑3:改了參數服務起不來
# 有些參數相互依賴,比如
net.core.netdev_max_backlog = 65535
# 要配合網卡驅動支持,不然可能有問題
建議一個個改,改完驗證,別一次改一堆。
坑4:容器環境
Docker/K8s環境下:
- 大部分網絡參數要在宿主機改
fs.file-max在容器裏可能改不了- 需要用
--sysctl參數或者securityContext
# K8s Pod配置
spec:
containers:
- name: app
securityContext:
sysctls:
- name: net.core.somaxconn
value: "65535"
監控建議
調完參數不是結束,要持續監控:
# 連接狀態分佈
ss -ant | awk '{print $1}' | sort | uniq -c
# 丟包情況
netstat -s | grep -E "dropped|overflow"
# 連接跟蹤表使用情況
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
寫個腳本定期採集,出問題才知道往哪查。
異地運維小技巧
我們有幾台服務器在異地機房,調參數的時候需要遠程操作。
之前用跳板機,現在用星空組網把幾台服務器組到一個虛擬網絡裏,直接SSH就能連,調參數方便多了。
總結
Linux內核參數調優核心就幾個方向:
|
方向
|
關鍵參數
|
常見問題
|
|
監聽隊列
|
somaxconn, tcp_max_syn_backlog
|
高併發連接失敗
|
|
TIME_WAIT
|
tcp_tw_reuse, tcp_fin_timeout
|
端口耗盡
|
|
緩衝區
|
tcp_rmem, tcp_wmem
|
大文件傳輸慢
|
|
連接跟蹤
|
nf_conntrack_max
|
防火牆導致丟包
|
|
文件描述符
|
file-max, nofile
|
too many open files
|
記住幾個原則:
- 先定位問題再調參數,別瞎調
- 改完要驗證,壓測或者灰度
- 留好回滾方案
- 持續監控,別調完就忘了
有內核調優經驗的歡迎評論區交流~