6.2 實現(xiàn)Nginx TCP負載均衡
Nginx在1.9.0版本開始支持tcp模式的負載均衡, 在1.9.13版本開始支持udp協(xié)議的負載均衡, udp主要用于DNS的域名解析, 其配置方式和指令和http代理類似, 其基于ngx_stream_proxy_module模塊實現(xiàn)tcp負載, 另外基于模塊ngx_http_upstream_module實現(xiàn)后端服務器分組轉發(fā), 權重分配, 狀態(tài)監(jiān)測, 調度算法等高級功能
如果是編譯安裝, 需要指定--with-stream選項才能支持ngx_stream_proxy_module模塊
6.2.1 tcp 負載均衡配置參數
stream { # 定義stream相關的服務, 定義在main語句塊和http平級
upstream backend { # 定義后端服務器
hash $remote_addr consistent; # 定義調度算法
server backend1.example.com:12345 weight=5; # 定義具體server
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}
upstream dns { # 定義后端服務器
server 10.0.0.1:53535; # 定義具體server
server dns.example.com:53;
}
server { # 定義server, 定義nginx如何接收和轉發(fā)遠程用戶的請求
listen 12345; # 監(jiān)聽ip:port
proxy_connect_timeout 1s; # 連接超時時間
proxy_timeout 3s; # 轉發(fā)超時時間
proxy_pass backend; # 轉發(fā)到具體服務器組
}
server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
}
6.2.2 負載均衡案例: Redis
6.2.2.1 準備環(huán)境
準備兩臺后端服務器, 安裝redis
可以基于每臺服務器的run_id測試調度結果
yum -y install redis
vim /etc/redis.conf
bind 0.0.0.0
systemctl enable --now redis
6.2.2.2 nginx配置負載均衡
# 先在nginx主配置文件定義tcp負載均衡的子配置文件路徑
[13:50:26 root@nginx ~]#vim /apps/nginx/conf/nginx.conf
include /apps/nginx/conf/tcp/tcp.conf; # 注意: tcp負載均衡的子配置文件路徑指令要和http語句塊平級, 一般寫在主配置文件最后即可, 由于stream是一級語句塊, 整個nginx只能有一個, 因此, 所有的tcp/udp負載均衡配置, 都寫在同一個文件里
[00:30:17 root@nginx /apps/nginx/conf/tcp]#vim redis.conf
stream {
upstream redis-server {
server 10.0.0.85:6379 weight=2;
server 10.0.0.84:6379 weight=1;
}
server{
# 配置負載均衡時, server語句塊不支持server_name, 客戶端直接訪問nginx的ip地址和端口
listen 6379;
proxy_pass redis-server;
}
}
[00:35:51 root@nginx /apps/nginx/conf/tcp]#nginx -s reload
[13:51:16 root@nginx ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:6379 # 驗證監(jiān)聽6379端口 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
6.2.2.3 客戶端連接nginx測試
# 可以看到1:2調度
[00:38:02 root@client ~]#redis-cli -h 10.0.0.86 info server | grep run_id
run_id:6c86d33bf1002c7839f43a6ac9055f0406d61b7a
[00:38:25 root@client ~]#redis-cli -h 10.0.0.86 info server | grep run_id
run_id:580343970ae2d5078ff064260e170a8932a48338
[00:38:27 root@client ~]#redis-cli -h 10.0.0.86 info server | grep run_id
run_id:6c86d33bf1002c7839f43a6ac9055f0406d61b7a
[00:38:28 root@client ~]#redis-cli -h 10.0.0.86 info server | grep run_id
run_id:6c86d33bf1002c7839f43a6ac9055f0406d61b7a
6.2.3 負載均衡案例: MySQL

圖片.png
6.2.3.1 準備環(huán)境
為了測試效果, 后端分別使用mariadb和mysql
數據庫上創(chuàng)建用戶, 需要對nginx的ip地址進行授權
nginx基于四層的調度是偽四層, 因此nginx會拆分請求和響應報文, 重新封裝
# 10.0.0.85 - MySQL
[23:34:16 root@mysql ~]#yum -y install mysql-server
[23:35:30 root@mysql ~]#systemctl enable --now mysqld
Created symlink /etc/systemd/system/multi-user.target.wants/mysqld.service → /usr/lib/systemd/system/mysqld.service.
[23:42:31 root@mysql ~]#mysql -e 'create user admin@"10.0.0.%" identified by "000000"'
# 10.0.0.84 - MariaDB
[23:34:41 root@mariadb ~]#yum -y install mariadb-server
[23:35:13 root@mariadb ~]#systemctl enable --now mariadb
Created symlink /etc/systemd/system/mysql.service → /usr/lib/systemd/system/mariadb.service.
Created symlink /etc/systemd/system/mysqld.service → /usr/lib/systemd/system/mariadb.service.
Created symlink /etc/systemd/system/multi-user.target.wants/mariadb.service → /usr/lib/systemd/system/mariadb.service.
[23:44:03 root@mariadb ~]#mysql -e 'create user admin@"10.0.0.%" identified by "000000"'
6.2.3.2 nginx配置負載均衡
# 單獨指定存放tcp負載均衡的配置文件, 關于tcp的負載均衡配置, 都可以寫到tcp目錄下某個.conf文件里, 因為stream是一級語句塊, 一個服務器只能有一個, 因此只能存在一個.conf配置文件, 專門來配置tcp負載均衡, 如果多個文件都有stream模塊, 那么重啟nginx會報錯
include /apps/nginx/conf/tcp/*.conf;
[23:47:05 root@nginx /apps/nginx/conf]#mkdir /apps/nginx/conf/tcp
[23:47:44 root@nginx /apps/nginx/conf]#cd /apps/nginx/conf/tcp
[23:47:45 root@nginx /apps/nginx/conf/tcp]#
[23:47:46 root@nginx /apps/nginx/conf/tcp]#
[23:47:46 root@nginx /apps/nginx/conf/tcp]#vim mysql.conf
[23:47:46 root@nginx /apps/nginx/conf/tcp]#vim mysql.conf
stream {
upstream mysql-server { # upstream定義后端服務器組
server 10.0.0.85:3306 max_fails=3 fail_timeout=30s;
server 10.0.0.84:3306; # 后端服務器監(jiān)聽的端口
}
server { # server定義nginx如何接收和處理客戶端請求, 包括監(jiān)聽的端口, 和轉發(fā)到的后端群組
listen 3306; # 面對客戶端的端口
proxy_pass mysql-server;
}
}
[23:59:02 root@nginx /apps/nginx/conf/tcp]#nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[23:59:05 root@nginx /apps/nginx/conf/tcp]#nginx -s reload
[23:59:10 root@nginx /apps/nginx/conf/tcp]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:3306 0.0.0.0:*
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
6.2.3.3 客戶端連接nginx測試
# 10.0.0.187安裝mysql客戶端
[00:00:27 root@client ~]#yum -y install mysql
# 連接nginx
[00:00:44 root@client ~]#mysql -h 10.0.0.86 -uadmin -p000000
MySQL [(none)]>
# 驗證版本

圖片.png
此時后端服務器會認為是nginx在訪問, 因此數據庫授權也是針對nginx進行授權

圖片.png
通過nginx的tcp負載均衡, 可以實現(xiàn)對后端的PXC集群進行調度

圖片.png
補充: lvs和nginx四層負載均衡的區(qū)別
nginx對于tcp的負載均衡實際是偽四層, 因為nginx會代替客戶端向后端服務器發(fā)起請求, 而不是單獨的轉發(fā), 后端服務器看到的是nginx服務器的ip地址
lvs對于tcp的負載均衡是只轉發(fā), 后端服務器看到的是客戶端的源ip地址