1. 程式人生 > >如何構建高效能伺服器(以Nginx為例)

如何構建高效能伺服器(以Nginx為例)

### 方法論 #### 軟體層面 ##### 增大CPU利用率 - 使用全部CPU, worker程序數等於CPU - 程序間不做無用的切換 - 繁忙時不主動讓出CPU - worker程序之間不爭搶CPU - CPU切換需要5us,如果大量程序需要切換,則CPU會浪費大量的時間切換,做無用功 - worker程序繫結CPU > pidstat -w可以檢視某個程序的切換次數 - 不被其他程序搶佔資源 - 提高程序優先順序,獲得更大的CPU時間片 - 減少其他程序 - 減少驚群 場景:多個worker程序accept同一個埠時 - 預設accept_mutex on 多個worker程序爭搶鎖獲得連線,同時只有一個worker獲得連線 - accept_mutex off 一個連線請求喚醒所有worker程序,同時只有一個worker獲得連線,存在驚群問題,當worker程序數不多時,影響不大,少了爭鎖,高併發時可以提高系統響應能力 - SO_REUSEPORT 核心3.9+處理大併發連線新特性,開啟後,連線通過核心分配worker程序,效能最好 - 提高CPU快取命中率 繫結worker到指定CPU: worker_cpu_affinity cpumask... ##### 增大記憶體利用率 - 使用tcmalloc 減少記憶體碎片 併發能力高於glibc,併發數越多,效能越能體現(小記憶體分配) google-perftools/.../tcmalloc.html 需要手動編譯到nginx ##### 增大IO利用率 - 對比 機械硬碟 - 價格低 - 儲存量大 - BPS大,適合順序讀寫 - IOPS小,不適合隨機讀寫 - 壽命長 固態應胖 - 價格高 - 儲存量小 - BPS大 - IOPS大 - 寫壽命短 - 優化讀取 - sendfile零拷貝 檔案直接從核心態的檔案到socket的傳遞 ``` location /video/{ sendfile on; aio on; directio 8m; } ``` - gzip_static 提前壓縮檔案,加快gzip報文的返回 - 記憶體盤/SSD盤 - 減少寫入 - empty_gif 使用返回一張1*1的空白圖片,以減少http的返回報文長度 - AIO 在磁碟讀寫時,程序可以處理其他事情 aio on|off|threads=[pool] - 直接IO,減少一次快取的讀寫 directio size|off 超過size則使用直接io,適合大檔案 - 增大error_log級別 - error.log輸出到記憶體 error_log memory: 32m debug 日誌在32m的記憶體進行迴圈輸出,只能看到32m的除錯日誌,可以提高效能 - 關閉access_log - 壓縮access_log access_log path [format] [gzip] - 是否開啟proxy buffering - syslog替代本地io 使用UDP寫入代替io寫入,提高效能 - 執行緒池thread pool 當某些io會阻塞時,使用執行緒池 ##### 增大網路寬頻利用率 - syn重試次數 net.ipv4.tcp_syn_retries = 6 - 本地埠可用範圍 net.ipv4.ip_local_port_range=32768 60999 可以放大 - 連線超時 proxy_connect_timeout - 接收連線最大個數(syn未完成握手) net.ipv4.tcp_max_syn_backlog = 262144 可以適當放大 - 已完成握手 net.core.somaxconn:系統最大backlog佇列長度 - 超出佇列可以接收報文直接回RST net.ipv4.tcp_abort_on_overflow - 未被核心處理的報文佇列長度 net.core.netdev_max_backlog - syn/ack重試次數 net.ipv4.tcp_synack_retries - 處理syn攻擊 net.ipv4.tcp_syncookies=1 > 當syn佇列滿後,新的syn不進入佇列,計算出cookie返回客戶端,客戶端攜帶cookie重新連線,伺服器驗證cookie,通過則建立連線。回導致TCP可選功能失效,例如擴充視窗/時間戳等 - 作業系統最大控制代碼 fs.file-max: 作業系統可以使用最大控制代碼數 使用fs.file-nr可以檢視當前已分配/正使用/上限 - 使用者最大控制代碼數 /etc/security/limits.conf root soft nofile 63535 root har nofile 65535 - 程序限制最大控制代碼數 worker_rlimit_nofile number - 程序最大連線數 worker_connections number - Tcp Fast Open 當TCP再次連線時,通過攜帶cookie,減少一次syn/ack的rtt時間,達到快速建立TCP連線的目的 ![nginxperformace-tfo](http://upload-images.jianshu.io/upload_images/24077087-868e65652b7fd562.PNG) net.ipv4.tcp_fastopen 0|1|2|3 listen address [:port] [fastopen=number]; > fastopen=number為了防止帶資料的syn攻擊,限制最大長度,指定TFO連線佇列的最大長度 - TCP緩衝區 net.ipv4.tcp_rmen = 4096 87380 6291456 net.ipv4.tcp_wmen = 4096 87380 6291456 net.ipv4.tcp_men = 1541646 2055528 3083292 net.ipv4.tcp_moderate_rcvbuf=1開啟自動調節快取模式 listen address [:port] [recvbuf=size] [sndbuf=size] net.ipv4.tcp_adv_win_scale = 1 應用快取 = buffer / (2^tcp_adv_win_scale) 接收視窗 = buffer - buffer/(2^tcp_adv_win_scale) BDP = 頻寬* RTT/2 buffer=BDP - Nagle演算法 網路中只存在一個未被確認的小報文ACK 目的:避免一個連線上存在大量的小報文,提高網路利用率 吞吐量優先:啟用Nagle tcp_nodelay off 低延時優先:禁用Nagle tcp_nodelay on - 擁塞視窗 實際流量=擁塞視窗和接收視窗的最小值 - 慢啟動 指數擴充套件擁塞視窗cwnd = cwnd*2 - 擁塞避免 視窗大於threshold線性增大 - 擁塞發生 發生丟包, RTO超時,threshold = cwnd/2, cwnd=1 Fast Retransmit: cwnd=cwnd/2, threshold=cwnd - 快速恢復 當Fast Retransmit出現時,cwnd調整為threshold+3*MSS - 優化慢啟動 增大初始cwnd=10 - TCP keep-alive 開啟keepalive可以探測到失去連線的socket,並即時關閉,節省系統資源 net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_keepalive_probes = 9 - timewait net.ipv4.tcp_orphan_retries = 0 net.ipv4.tcp_fin_timeout = 60 net.ipv4.tcp_max_tw_buckets = 262144 最大timewait連線數,超出直接關閉連線 - lingering_close延遲關閉 當接收緩衝依然接收到客戶端的內容,伺服器如果馬上傳送RST關閉連線,會導致客戶端由於接收到RST而忽略http response lingering_close off|on|always reset_timedout_connection on|off; 當讀寫超時生效依法連線關閉,通過傳送RST馬上關閉連線,以釋放資源 - TLS/SLL優化握手 ssl_session_cache - TLS/SSL會話票證tickets Nginx將會話session中的資訊作為tickets加密傳送給客戶端,當客戶端再次建立連線時帶上tickets,Nignx驗證複用session 優點可以減少對稱加解密的次數,提高效能 缺點降低安全性,需要經常更換tickets金鑰 ssl_seesion_tickets on|off ssl_session_ticket_key file - 使用HTTP長連線 keepalive_request number; - gzip壓縮 提高網路傳輸效率 gzip on|off - 使用http2 ##### 統計函式呼叫統計 google-perltool pprof --text|pdf goodle_perftools_profiles file #### 硬體 - 網絡卡:萬兆網絡卡,例如10G/25G/40G - 磁碟:固態硬碟,關注IOPS/BPS指標 - CPU:更快的主頻,更大的快取,更優的架構 - 記憶體:更快的訪問速度 #