一、4層的負載均衡
Nginx Plus的商業授權版開始具有TCP負載均衡的功能。從Nginx 1.7.7版本開始加入的,現在變成了一個商業收費版本,想要試用,需要在官網申請。也就是說,Nginx除了以前常用的HTTP負載均衡外,Nginx增加基於TCP協議實現的負載均衡方法。 HTTP負載均衡,也就是我們通常所有“七層負載均衡”,工作在第七層“應用層”。而TCP負載均衡,就是我們通常所說的“四層負載均衡”,工作在“網絡層”和“傳輸層”。例如,LVS(Linux Virtual Server,linux虛擬服務)和F5(一種硬件負載均衡設備),也是屬於“四層負載均衡”。
二、nginx的TCP的反向代理
通常我們使用Nginx的upstream做基於http/https端口的7層負載均衡,tcp/udp端口的四層負載均衡一般用LVS或者Haproxy來做。
有兩種方式:
1、使用第三方模塊nginx_tcp_proxy_module,需要在編譯時增加tcp代理模塊【nginx_tcp_proxy_module】
2、nginx從1.9.0開始,新增加了一個stream模塊,用來實現四層協議的轉發、代理或者負載均衡等。這完全就是搶HAproxy份額的節奏,鑒於nginx在7層負載均衡和web service上的成功,和nginx良好的框架,stream模塊前景一片光明。
nginx-1.9.0 已發布,該版本增加了 stream 模塊用於一般的 TCP 代理和負載均衡。
The
ngx_stream_core_module
module is available since version 1.9.0. This module is not built by default, it should be enabled with the--with-stream
configuration parameter.ngx_stream_core_module 這個模塊在1.90版本后將被啟用。但是並不會默認安裝,需要在編譯時通過指定 –with-stream 參數來激活這個模塊。
其他改進包括:
- Change: 刪除過時的 aio 和 rtsig 事件處理方法
- Feature: 可在 upstream 塊中使用 “zone” 指令
- Feature: 流模塊,支持 TCP 代理和負載均衡
- Feature: ngx_http_memcached_module 支持字節范圍
- Feature: Windows 版本支持使用共享內存,帶隨機化地址空間布局.
- Feature: “error_log” 指令可在 mail 和 server 級別
- Bugfix: the “proxy_protocol” parameter of the “listen” directive did not work if not specified in the first “listen” directive for a listen socket.
所以,我們如果需要用到這個功能,就需要加上 –with-stream 參數重新編譯nginx。
在了解了實現方法后,再了解下安裝方案:
- 高版本的nginx(1.10以上?)不支持第三方模塊nginx_tcp_proxy_module的安裝;
- 高版本的nginx有自帶tcp負載均衡配置(stream模塊),但是health_check功能只供商業用戶使用,第三方tcp心跳檢測模塊還沒有適配上(2018.5);
- 低版本的nginx可以用第三方模塊nginx_tcp_proxy_module實現tcp負載均衡並且支持用check進行心跳檢測,打補丁安裝第三方模塊nginx_tcp_proxy_module來實現tcp負載均衡和心跳檢測;
高版本nginx + nginx_tcp_proxy_module(第三方模塊不支持) --> 高版本nginx stream(雖然可轉發,但health_check暫不可用,未見適配的第三方心跳檢測模塊) --> 低版本的nginx(安裝第三方模塊實現tcp負載均衡)。
所以可行的還只有低版本的nginx(安裝第三方模塊實現tcp負載均衡)。--來源網絡未經驗證
三、nginx_tcp_proxy_module安裝及使用
nginx tcp代理功能由nginx_tcp_proxy_module模塊提供,同時監測后端主機狀態。該模塊包括的模塊有: ngx_tcp_module, ngx_tcp_core_module, ngx_tcp_upstream_module, ngx_tcp_proxy_module, ngx_tcp_upstream_ip_hash_module。
3.1、安裝步驟:
cd /app
wget http://nginx.org/download/nginx-1.6.3.tar.gz unzip nginx-1.6.3.tar.gz wget https://github.com/yaoweibin/nginx_tcp_proxy_module/archive/master.zip unzip master cd /app/nginx-1.6.3 patch -p1 </app/nginx_tcp_proxy_module-master/tcp.patch ./configure --add-module=/app/nginx_tcp_proxy_module-master make make install
3.2、nginx.conf文件中配置負載均衡參數
tcp {
upstream server { server 10.100.138.15:8787; server 10.100.138.30:8787; #check interval 健康檢查時間間隔,單位為毫秒 #rise 檢查幾次正常后,將server加入以負載列表中 #fall 檢查幾次失敗后,從負載隊列移除server #timeout 檢查超時時間,單位為毫秒 check interval=3000 rise=2 fall=5 timeout=1000; } server { listen 8787; proxy_pass server;
so_keepalive on;
- tcp_nodelay on;
} }
客戶端的長連接會斷開,沒有進展。
TCP負載均衡原理上和LVS等是一致的,工作在更為底層,性能會高於原來HTTP負載均衡不少。但是,不會比LVS更為出色,LVS被置於內核模塊,而Nginx工作在用戶態,而且,Nginx相對比較重。
四、nginx stream安裝及使用
環境:centOS7.3_1611 物理服務器一台
Nginx版本:1.12.1
1.下載NGINX穩定發行版
https://nginx.org/download/nginx-1.12.1.tar.gz
2.解壓並切換到安裝目錄
tar -zxvf nginx-1.12.1.tar.gz
cd nginx-1.12.1
3.編譯安裝
yum -y install gcc gcc-c++ autoconf automake yum -y install zlib zlib-devel openssl openssl-devel pcre-devel ./configure --prefix=/opt/nginx --sbin-path=/opt/nginx/sbin/nginx --conf-path=/opt/nginx/conf/nginx.conf --with-http_stub_status_module --with-http_gzip_static_module --with-stream make make install cd /opt/nginx
4.修改配置文件
vim /opt/nginx/conf/nginx.conf(在配置文件最后行添加如下)
stream {
upstream NAME1 {
hash $remote_addr consistent;
server 10.22.0.7:5000 max_fails=3 fail_timeout=30s;
server 10.22.0.8:5000 max_fails=3 fail_timeout=30s;
}
upstream NAME2 {
hash $remote_addr consistent;
server 192.168.5.8:8080 max_fails=3 fail_timeout=30s;
}
server{
listen 8080;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass NAME1;
}
server{
listen 60000;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass NAME2;
}
}
解析:
如上配置文件的含義為
將端口8080反向代理NAME1組的serverIP:PORT,最大失敗次數為3,超時時間為30秒;
將端口60000反向代理NAME2組的serverIP:PORT,最大失敗次數為3,超時時間為30秒。
5.檢測語法
/opt/nginx/sbin/nginx -t
6.開啟NGINX
/opt/nginx/sbin/nginx
7.重啟NGINX
/opt/nginx/sbin/nginx -s reload
這里推薦使用reload而不是restart。
8.訪問IP:PORT驗證是否生效
stream core 一些變量
(注意:變量支持是從 nginx 1.11.2版本開始的)
$binary_remote_addr
二進制格式的客戶端地址
$bytes_received
從客戶端接收到的字節數
$bytes_sent
發往客戶端的字節數
$hostname
連接域名
$msec
毫秒精度的當前時間
$nginx_version
nginx 版本
$pid
worker進程號
$protocol
通信協議(UDP or TCP)
$remote_addr
客戶端ip
$remote_port
客戶端端口
$server_addr
接受連接的服務器ip,計算此變量需要一次系統調用。所以避免系統調用,在listen指令里必須指定具體的服務器地址並且使用參數bind。
$server_port
接受連接的服務器端口
$session_time
毫秒精度的會話時間(版本1.11.4開始)
$status
會話狀態(版本1.11.4開始), 可以是一下幾個值:
200
成功
400
不能正常解析客戶端數據
403
禁止訪問
500
服務器內部錯誤
502
網關錯誤,比如上游服務器無法連接
503
服務不可用,比如由於限制連接等措施導致
$time_iso8601
ISO 8601時間格式
$time_local
普通日志格式的時間戳
五、TCP負載均衡的執行原理
當Nginx從監聽端口收到一個新的客戶端鏈接時,立刻執行路由調度算法,獲得指定需要連接的服務IP,然后創建一個新的上游連接,連接到指定服務器。
TCP負載均衡支持Nginx原有的調度算法,包括Round Robin(默認,輪詢調度),哈希(選擇一致)等。同時,調度信息數據也會和健壯性檢測模塊一起協作,為每個連接選擇適當的目標上游服務器。如果使用Hash負載均衡的調度方法,你可以使用$remote_addr(客戶端IP)來達成簡單持久化會話(同一個客戶端IP的連接,總是落到同一個服務server上)。
和其他upstream模塊一樣,TCP的stream模塊也支持自定義負載均和的轉發權重(配置“weight=2”),還有backup和down的參數,用於踢掉失效的上游服務器。max_conns參數可以限制一台服務器的TCP連接數量,根據服務器的容量來設置恰當的配置數值,尤其在高並發的場景下,可以達到過載保護的目的。
Nginx監控客戶端連接和上游連接,一旦接收到數據,則Nginx會立刻讀取並且推送到上游連接,不會做TCP連接內的數據檢測。Nginx維護一份內存緩沖區,用於客戶端和上游數據的寫入。如果客戶端或者服務端傳輸了量很大的數據,緩沖區會適當增加內存的大小。
當Nginx收到任意一方的關閉連接通知,或者TCP連接被閑置超過了proxy_timeout配置的時間,連接將會被關閉。對於TCP長連接,我們更應該選擇適當的proxy_timeout的時間,同時,關注監聽socke的so_keepalive參數,防止過早地斷開連接。
服務健壯性監控
TCP負載均衡模塊支持內置健壯性檢測,一台上游服務器如果拒絕TCP連接超過proxy_connect_timeout配置的時間,將會被認為已經失效。在這種情況下,Nginx立刻嘗試連接upstream組內的另一台正常的服務器。連接失敗信息將會記錄到Nginx的錯誤日志中。
如果一台服務器,反復失敗(超過了max_fails或者fail_timeout配置的參數),Nginx也會踢掉這台服務器。服務器被踢掉60秒后,Nginx會偶爾嘗試重連它,檢測它是否恢復正常。如果服務器恢復正常,Nginx將它加回到upstream組內,緩慢加大連接請求的比例。
之所“緩慢加大”,因為通常一個服務都有“熱點數據”,也就是說,80%以上甚至更多的請求,實際都會被阻擋在“熱點數據緩存”中,真正執行處理的請求只有很少的一部分。在機器剛剛啟動的時候,“熱點數據緩存”實際上還沒有建立,這個時候爆發性地轉發大量請求過來,很可能導致機器無法“承受”而再次掛掉。以MySQL為例子,我們的mysql查詢,通常95%以上都是落在了內存cache中,真正執行查詢的並不多。
其實,無論是單台機器或者一個集群,在高並發請求場景下,重啟或者切換,都存在這個風險,解決的途徑主要是兩種:
(1)請求逐步增加,從少到多,逐步積累熱點數據,最終達到正常服務狀態。
(2)提前准備好“常用”的數據,主動對服務做“預熱”,預熱完成之后,再開放服務器的訪問。
TCP負載均衡原理上和LVS等是一致的,工作在更為底層,性能會高於原來HTTP負載均衡不少。但是,不會比LVS更為出色,LVS被置於內核模塊,而Nginx工作在用戶態,而且,Nginx相對比較重。