Nginx取代F5
接到指示,新上線的專案將不再使用F5,要求使用Nginx來取代5,以下就記錄一下過程中所踩到的坑
架構 :
使用者 → 反代 → Google Cloud SLB → 兩台Nginx SLB → 後端服務器
反代 : 用Nginx搭建的反向代理
Google Cloud SLB主要目地在於把流量和請求平均分散給兩台Nginx SLB
Nginx 作業系統安裝 :
作業系統 : Centos 7.9 + Tengine
系統相關參數更改 :
/etc/sysctl.conf
#禁用IPV6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
vm.swappiness = 0 #停用swap
fs.file-max = 200000000 #增加最大檔案開啟數量
fs.nr_open = 300000000 #增加最大檔案開啟數量
net.ipv4.neigh.default.gc_stale_time=120 #增加ARP過期時間,減少ARP請求
#禁用反向路由過濾,代表允許來自非預期路由的封包進入接口
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
#只發送ARP封包
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.all.arp_announce=2
net.ipv4.tcp_max_tw_buckets = 5000 #TCP Time-Wait狀態的數量上限
net.ipv4.tcp_syncookies = 1 #啟用TCP SYN Cookies
net.ipv4.tcp_max_syn_backlog = 3000 #設定系統TCP SYN佇列的最大長度。當有大量連線請求進來時,如果佇列長度超過這個設定值,後續的連線請求將被丟棄。增加此值可能提高系統處理連線請求的能力
net.ipv4.tcp_synack_retries = 1 #此參數用於設定在接收到SYN+ACK封包後,等待客戶端ACK確認的最大重試次數
net.core.somaxconn = 50000 #設定伺服器TCP緩衝區中最大的連線佇列長度
net.ipv4.tcp_tw_recycle = 0 #禁用TCP Time-Wait狀態的快速回收機制
net.ipv4.tcp_tw_reuse = 1 #啟用TCP Time-Wait狀態的快速重用機制
net.ipv4.tcp_fin_timeout = 30 #系統會等待30秒後將TCP連線完全關閉,並釋放相關資源
#TCP緩衝區的記憶體使用限制
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
net.ipv4.ip_local_port_range = 1024 65535
#TCP port range
/etc/security/limit.conf
#設定使用者(或進程)在執行期間可以打開的最大文件描述符(file descriptor)數量。
* - nofile 65535
Nginx 相關設定 :
nginx.conf
worker_processes auto; #Nginx自動根據可用的CPU核心數量來設定工作進程的數量
worker_cpu_affinity auto; #Nginx自動設定親和性,以確保工作進程在不同核心上均勻分佈
worker_rlimit_nofile 655350; #定每個工作進程打開文件描述符的最大數量
events {
accept_mutex off; #關閉了互斥鎖,多個工作進程可以同時處理新連線,這可能提高伺服器的並發能力
worker_connections 65535; #每個工作進程可以同時處理的最大連線數量
multi_accept on; #一個工作進程可以同時接受多個連線請求
use epoll; #在支援epoll的Linux系統上,使用此設定可以提高伺服器的效率,特別是在處理大量並發連線時
}
sendfile on; #啟用sendfile可以大幅提高Nginx伺服器傳送靜態檔案的效率和效能。
keepalive_timeout 65; #當連線閒置 65 秒後,Nginx 伺服器將關閉連線。這可以幫助節省伺服器資源,但同時也確保連線不會無限期地保持開啟
underscores_in_headers on; #允許HTTP請求標頭中使用底線
#允許客戶端發送的請求主體大小最多為200MB。超過這個大小的請求將被拒絕
client_max_body_size 200m;
#表示使用1MB的緩衝區來暫存客戶端的請求主體
client_body_buffer_size 1m;
#表示Nginx將忽略客戶端中止連線,並繼續處理代理請求
proxy_ignore_client_abort on;
#如果在60秒內沒有收到完整的請求標頭或body,Nginx將結束與客戶端的連線
client_header_timeout 60;
client_body_timeout 60;
#連線至upstream timeout時間60秒
proxy_connect_timeout 60;
#發送至upstream請求的超時時間
proxy_send_timeout 600;
#讀取至upstream請求的超時時間
proxy_read_timeout 600;
#
每個keepalive連線最多可以處理10000個請求
keepalive_requests 10000;
Nginx server 區塊
upstream backendserver {
server 10.140.0.8:61000 max_fails=5 fail_timeout=5s; #定義兩台後端服務器IP及端口,連續失敗5次,將該服務器設定為失效,失敗超時為5秒
server 10.140.0.9:61000 max_fails=5 fail_timeout=5s;
#透過http方式進行健康檢查,每30秒檢查一次
,失敗超時為8秒,連續2次健康檢查都成功算成功,連續3次失敗就算失效
check interval=30000 rise=2 fall=3 timeout=8000 type=http;
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\nHost: testweb.com\r\n\r\n"; #發送一個HEAD請求到指定的後端伺服器,並設定了一些HTTP標頭
check_http_expect_alive http_2xx http_3xx http_4xx; #HTTP 2xx、3xx、4xx的響應狀態碼都被認為是正常的
keepalive 300;
session_sticky cookie=uid; #設定會話黏著(session sticky),這裡是根據名為"uid" 的cookie來實現
}
server
{
listen 80 reuseport; #reuseport 讓Nginx可以在多個工作進程(worker process)之間共享網絡端口,這樣可以更有效地處理連線和請求
server_name testweb.com;
include myconf/proxy.conf; #引入相關設定
location / {
proxy_pass http://backendserver/;
}
access_log /usr/local/nginx/logs/testweb.log main;
}
proxy.conf
proxy_redirect off; #可以確保這些重定向URL正確地傳送給客戶端,而不會被修改
proxy_http_version 1.1; #Nginx將使用HTTP/1.1版本與後端代理伺服器進行通訊
proxy_set_header Connection ""; #Nginx不會在請求中包含Connection標頭
#斷點續傳或下載大檔案的部分內容
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
proxy_no_cache $http_range $http_if_range;
proxy_set_header Host $host;
#判斷用戶端真實IP及完整跳轉IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
最主要的坑就是,RD經由wrk來進行壓測時,常常會報504的錯,後來查看之後,發現程式在處理時會耗時多秒
所以整個架構的每一個節點 : 反代/GCP SLB/nginx SLB上所有的time out時間都要跟著拉長
但是誰會想到,一個程式的耗時會大到超過預設的3秒以上?