Nginx TCP和UDP負載
負載均衡是指有效的通過多個后端服務器分發網絡流量。
Nginx能代理和負載均衡TCP、UDP通信。TCP(傳輸控制協議)、UDP(用戶數據包協議)是許多流行應用程序和服務的協議,例如LDAP、MySQL和RTMP使用TCP協議,DNS、syslog和RADIUS
2 需要使用--with-stream配置標記構建最新Nginx,或最新的Nginx+(不需要額外構建步驟)
應用程序、數據庫或服務基於TCP或UDP通信
Upstream服務器運行相同的應用程序、數據庫或服務實例
3 配置反向代理首先,你需要配置反向代理,因此,Nginx轉發來自客戶端的TCP連接或UDP數據包到upstream組或一個代理服務器。
打開Nginx配置文件並執行以下步驟:
創建頂級stream {}塊
stream {
...
}
在頂級stream {}上下文中為每個虛擬主機定義一個或多個server {}配置塊。
在每個server {}配置塊中包括listen指令定義服務器監聽的IP地址和/或端口。對於UDP通信,也包括udp參數。TCP是stream上下文的默認協議:
stream {
server {
listen 12345;
...
}
server {
listen 53 udp;
...
}
...
}
包括proxy_pass指令定義代理服務器或upstream組stream {
server {
listen 12345;
proxy_pass stream_backend;
}
server {
listen 12346;
proxy_pass backend.example.com:12346;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
...
}
可選,如果你的代理服務器多個網絡接口,你能配置Nginx選擇源IP地址連接到upstream服務器。代理服務器在Nginx后面配置為從特定IP網絡或IP地址范圍接收連接是有用的。指定proxy_bind指令和必要的網絡接口的IP地址:
stream {
...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_bind 127.0.0.1:12345;
}
}
可選,你能調整兩個內存緩存,Nginx能從客戶端和upstream連接放入數據。如果有一個體積小的數據,減少緩存可以節約內存資源。如果有大量數據,增加緩存大小減少套接字讀寫操作次數。一旦在一個連接接收到數據,Nginx讀取它並在其它連接轉發。緩存使用proxy_buffer_size指令控制:stream {
...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_buffer_size 16k;
}
}
4 配置TCP和UDP負載均衡為了配置負載均衡:
1、創建服務器組,或upstream組將負載均衡通信。定義一個或多個upstream {}配置塊在頂級steam {}上下文,設置upstream組的名字,例如,TCP服務器steam_backed和UDP服務器dns_servers:
stream {
upstream stream_backend {
...
}
upstream dns_servers {
...
}
...
}
2、在upstream組中填充upstream服務器。upstream {}塊中,為每個upstream服務器添加server指令,指定IP地址或主機名(解析多個IP地址)和必須的端口號。
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
...
}
upstream dns_servers {
server 192.168.136.130:53;
server 192.168.136.131:53;
...
}
...
}
3、配置負載均衡方法
round-robin(輪詢)——默認,Nginx使用輪詢算法負載均衡通信。因為是默認方法,所以沒有round-robin指令;只創建upstream配置塊在頂級stream上下文並像之前步驟添加server指令。
last_conn(最少連接)——Nginx選擇當前活躍連接數較少的服務器。
least_tome——Nginx選擇最低平均延遲和最少活躍連接的服務器。最低活躍連接基於least_time指令的以下參數計算:
connect——連接upstream服務器的時間
first_byte——接收第一個數據字節的時間
last_byte——從服務器接收完整響應的時間
upstream stream_backend {
least_time first_byte;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
hash——Nginx基於用戶定義鍵選擇服務器,例如,源IP地址upstream stream_backend {
hash $remote_addr;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
hash負載均衡方法也用於配置回話持久化。哈希函數基於客戶端IP地址,來自指定客戶端的連接總是傳遞給相同的服務器,除非服務器宕機或不可用。指定一個可選的consistent參數應用ketama一致性哈希方法
hash $remote_addr consistent;
4、可選,指定最大連接數、服務器權重等
upstream stream_backend {
hash $remote_addr consistent;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
...
}
如果你通過主機名標識服務器,配置主機名解析多個IP地址,然后Nginx通過IP地址使用輪詢算法負載均衡。在這種情況下,你必須在proxy_pass指令中指定服務器的端口號,不必指定協議:
stream {
...
server {
listen 12345;
proxy_pass backend.example.com:12345;
}
}
5 被動健康檢查如果試圖連接upstream服務器超時或出錯,Nginx標記服務器為不可用並在指定時間內停止發送請求給該服務器。為了定義不可用條件,包括以下參數到server指令:
fail_timeout——同Nginx負載均衡章節
max_fails——同Nginx負載均衡章節
fail_timeout默認為10秒,max_fails默認為1次。因此,如果連接10秒內嘗試至少一次失敗,Nginx標記服務器10秒內不可用。
upstream stream_backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
server backend3.example.com:12346 max_conns=3;
}
6 主動健康檢查健康檢查能配置測試廣范圍的錯誤類型。例如,Nginx能不斷測試upstream服務器的響應能力並避免服務器故障。
6.1 工作原理Nginx發送特定健康檢查請求到每個upstream服務器並檢查響應滿足某一條件。如果不能連接到服務器,那么健康檢查失敗,服務器不健康。Nginx不代理客戶端連接到不健康的服務器。如果多個健康檢查定義在服務器組中,相應服務器的任意一個檢查不通過該服務器都是不健康的。
6.2 預備條件你在stream上下文中配置upstream服務器組
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
}
你配置一台服務器傳遞通信(在這種情況下,是TCP連接)到服務器組server {
listen 12345;
proxy_pass stream_backend;
}
6.3 基礎配置指定共享內存區域
stream {
upstream stream_backend {
zone stream_backend 64k;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
}
啟用健康檢查server {
listen 12345;
proxy_pass stream_backend;
health_check;
health_check_timeout5s;
}
health_check指令啟用健康檢查功能,health_check_timeout覆蓋健康檢查的proxy_timeout。
為了啟用健康檢查UDP通信,為health_check指令指定udp參數:
server {
listen 5053;
proxy_pass dns_servers;
health_check udp;
health_check_timeout 5s;
}
6.4 健康檢查調優默認,Nginx嘗試每5秒連接upstream服務器組中的每台服務器。如果不能建立連接,Nginx認為健康檢查失敗,標記為不健康,停止轉發客戶端連接到服務器。
為了改變默認行為,包括參數到health_check指令:
interval——Nginx多久發送一次健康檢查請求(默認5秒)
passes——服務器連續多少次響應健康檢查認為是健康(默認是1次)
fails——服務器連續多少次健康檢查失敗認為是不健康(默認是1次)
server {
listen 12345;
proxy_pass stream_backend;
health_check interval=10 passes=2 fails=3;
}
在例子中,TCP健康檢查時間間隔增加到10秒,服務器認為連續3次健康檢查失敗是不健康,服務器需要連續2次通過健康檢查才再次認為是健康的。
默認,Nginx發送健康檢查消息給upstream塊中的server指令的特定端口。你能指定其它的健康檢查端口,當許多服務在相同主機檢查健康時非常有用。為了覆蓋端口,指定health_check指令的port參數:
server {
listen 12345;
proxy_pass stream_backend;
health_check port=8080;
}
6.5 使用match配置塊調優健康檢查你能通過配置大量健康檢查測試驗證服務響應。這些測試放置在stream{}上下文中的match {}配置塊。指定match {}塊並設置它的名字,例如,tcp_test:
stream {
...
match tcp_test {
...
}
}
然后在health_check指令包括match參數和match塊相同名稱引用塊:
stream {
server {
listen 12345;
health_check match=tcp_test;
proxy_pass stream_backend;
}
}
健康檢查的條件或測試使用send和expect參數設置:
send——發送給服務器文本字符串或十六進制字符(“/x”后面跟兩個十六進制數字) expect——服務器返回的數據匹配的字符串貨正則表達式這些參數能用於不同的組合,但不能同時制定超過一個send和一個expect參數。參數配置也依賴於使用(TCP或UDP)的協議。
6.5.1 調優TCP健康檢查為了調優TCP健康檢查,你能組合send和expect參數:
如果沒有send或expect參數指定,測試連接服務器能力。
如果expect參數被指定,服務器期望無條件發送數據:
match pop3 {
expect ~* "+OK";
}
如果send參數指定,它期望連接將成功建立並指定字符串發送給服務器:match pop_quit {
send QUIT;
}
如果send和expect參數被指定stream {
upstream stream_backend {
zone upstream_backend 64k;
server backend1.example.com:12345;
}
match http {
send "GET / HTTP/1.0rnHost: localhostrnrn";
expect ~* "200 OK";
}
server {
listen 12345;
health_check match=http;
proxy_pass stream_backend;
}
}
例子顯示為了健康檢查傳入,HTTP請求必須發送到服務器,並期望服務器結果包含”200 OK”表示HTTP響應成功。
6.5.2 UDP健康檢查調優為了調優UDP健康檢查,你應該指定send和expect參數:
NTP例子
match ntp {
send xe3x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00;
expect ~* x24;
}
DNS例子match dns {
send x00x2ax00x00x00x01x00x00x00x00x00x00x03x73x74x6cx04x75x6dx73x6cx03x65x64x75x00x00x01x00x01;
expect ~* "health.is.good";
}
7 動態配置Upstream服務器組能容易使用簡單的HTTP接口重新動態配置。使用該接口,你能瀏覽所有服務器在upstream組或特定服務器,修改服務器參數,並添加或刪除upstream服務器。
為了啟用動態配置:
創建頂級http {}塊或確保在你的配置文件中存在
http {
...
}
創建配置請求的location,例如,upstream_conf。http {
server {
location /upstream_conf {
...
}
}
}
在該location中指定upstream_conf指令——一個能用於解釋和重新配置upstream組的處理器http {
server {
location /upstream_conf {
upstream_conf;
...
}
}
}
限制該location的訪問
http {
server {
location /upstream_conf {
upstream_conf;
allow 127.0.0.1;
deny all;
}
}
}
創建共享內存區域stream {
upstream stream_backend {
zone backend 64k;
...
}
}
7.1 動態配置例子stream {
...
upstream appservers {
zone appservers 64k;
server appserv1.example.com:12345 weight=5;
server appserv2.example.com:12345 fail_timeout=5s;
server backup1.example.com:12345 backup;
server backup2.example.com:12345 backup;
}
server {
proxy_pass appservers;
health_check;
}
}
http {
...
server {
location /upstream_conf {
upstream_conf;
allow 127.0.0.1;
deny all;
}
}
}
瀏覽所有備機http://127.0.0.1/upstream_conf?stream=&upstream=appservers&backup=
添加新服務器到服務器組http://127.0.0.1/upstream_conf?stream=&add=&upstream=appservers&server=appserv3.example.com:12345&weight=2&max_fails=3
從服務器組刪除服務器http://127.0.0.1/upstream_conf?stream=&remove=&upstream=appservers&id=2
修改指定服務器http://127.0.0.1/upstream_conf?stream=&upstream=appservers&id=2&down=
8 TCP和UDP負載均衡配置例子stream {
upstream stream_backend {
least_conn;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
server backend3.example.com:12346 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
server 192.168.136.132:53;
}
server {
listen 12345;
proxy_pass backend;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
server {
listen 12346;
proxy_pass backend.example.com:12346;
}
}