1. 程式人生 > >Nginx實現反向代理負載均衡功能

Nginx實現反向代理負載均衡功能

運維 出現 正常 技術分享 remote eas ups 單個 搭建

反向代理軟件

Nginx:本身支持反向代理、負載均衡功能,屬於L7層負載均衡。Nginx反向代理簡單易用,受到大部分中小企業的青睞。
LVS:支持L4層負載均衡,
haproxy:支持L4、L7層負載均衡
L4、L7是指OSI模型中的第四層和第七層;L4:TCP負載均衡;L7:http負載均衡
nginx、lvs、haproxy區別參考資料
https://www.cnblogs.com/ahang/p/5799065.html
https://www.cnblogs.com/like-minded/p/5157659.html

實現Nginx負載均衡的兩個主要模塊
Nginx得負載均衡是基於反向代理之上實現的。
ngx_http_proxy_module: proxy代理模塊,把請求後拋給服務器節點或upstream服務器池

ngx_http_upstream_module: 負載均衡模塊,可以實現網站的負載均衡功能及節點的健康檢查,定義節點池
具體語法可以參考官方文檔:
http://nginx.org/en/docs/http/ngx_http_proxy_module.html
http://nginx.org/en/docs/http/ngx_http_upstream_module.html

Nginx反向代理軟件安裝
Nginx反向代理軟件安裝即安裝Nginx軟件。下面是安裝Nginx自動化腳本

#系統環境
cat /etc/redhat-release 
uname -r
uname -m
#設置目錄環境
mkdir /home/Ricky/tools -p
mkdir /application
mkdir /server/scripts -p
#安裝所需的庫
yum -y install pcre pcre-devel openssl-devel
rpm -qa pcre pcre-devel openssl-devel
#添加Nginx運行用戶
useradd -u 501 -s /sbin/nologin -M www
id www
mkdir /application/nginx-1.12.2 -p
#安裝Nginx
cd /home/Ricky/tools
wget -q http://nginx.org/download/nginx-1.12.2.tar.gz 
tar xf nginx-1.12.2.tar.gz
cd nginx-1.12.2
./configure --prefix=/application/nginx-1.12.2/ --user=www --group=www --with-http_ssl_module --with-http_stub_status_module 
echo $?
make
echo $?
make install
echo $?
ln -s /application/nginx-1.12.2/ /application/nginx
#開機啟動
echo "/application/nginx/sbin/nginx" >>/etc/rc.local 
tail -1 /etc/rc.local

Nginx反向代理部署

#生成配置文件nginx.conf
cd /application/nginx/conf/
egrep -v "#|^$" nginx.conf.default >nginx.conf
#配置反向代理和upstream資源池
vim nginx.conf
upstream www_server_pools {
        server 10.0.0.7:80 weight=1;
        server 10.0.0.8:80 weight=1;#weight權重相等,實現負載均衡,輪詢處理請求
}
    server {
        listen       80;
        server_name  www.ricky.com;
        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://www_server_pools;#把請求拋向upstream資源池,讓資源池的設備進行處理
            proxy_set_header Host  $host;#自定義http包的header的host字段,讓代理服務器使用用戶的host去訪問web服務器(不改變http中host的信息);如果不自動以host字段,可能會導致返回400的報錯
        }
    }
/application/nginx/sbin/nginx –t
/application/nginx/sbin/nginx -s reload
lsof -i :80

反向代理負載均衡測試結果
我配置了1臺nginx反向代理服務器和兩臺web服務器(一臺apache,一臺nginx);實際生產中要統一使用apache或者nginx,我這裏是因為我自己在家裏的電腦搭建了一個集群架構研究集群,web服務器只搭建了一臺apache和一臺nginx,湊合著用。這裏nginx proxy屬於單點,可以增加一臺結合keepalived做高可用,後續文章講解。

技術分享圖片

for n in `seq 100`;do curl 10.0.0.6;sleep 1;done
apache www
nginx www
apache www
nginx www

如果web集群中的一臺服務器宕機了,代理就會把所有請求轉發到剩下的那臺web服務器提供服務,不會造成用戶因為單個節點壞了,而無法訪問公司網站
upstream模塊具備健康檢查功能,所以能夠及時發現集群中宕機的節點,從而輪詢給正常工作的機器來處理,使用的是輪詢原理。

400錯誤出現的可能
在實驗的時候,客戶端返回信息出現錯誤,只有一臺web能正常返回內容,另一臺返回400的報錯信息。因為是以前的筆記,忘了把錯誤信息保留下來。
1、http報文缺失host字段
用戶到反向代理服務器中的http報文header請求頭中是有host字段的,而反向代理服務器到web服務器的http報文header請求頭中是沒有host字段的,所以導致apache服務器無法正常解析nginx代理轉發的請求,所以返回400錯誤(400-499是客戶端的問題)
在http 1.1中不能缺失host字段,如果缺失, 服務器返回400 bad request,http1.1中不能缺失host字段,但host字段可以是空值。
在http 1.0中可以缺失host字段。
參考資料:https://blog.csdn.net/s1234567_89/article/details/51139864
proxy_set_header Host $host;
#自定義http包的header的host字段,讓代理服務器使用用戶的host去訪問web服務器(不改變http中host的信息)
位置:http,server,location
參考資料:
https://www.cnblogs.com/yanghj010/p/5980974.html
https://blog.csdn.net/a19860903/article/details/49914131
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header

反向代理原理

技術分享圖片
查看web服務器的訪問日誌
10.0.0.6 - - [13/Jun/2018:20:44:15 +0800] "GET / HTTP/1.0" 200 10 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
客戶端IP是10.0.0.61;
nginx反向代理服務器是10.0.0.6;
從這裏可以看出,用戶訪問web是通過反向代理服務器完成的(用戶訪問反向代理服務器,然後由代理服務器去請求web集群,獲取數據後,也是由代理服務器響應用戶)

web端如何記錄用戶ip?
web節點服務器訪問日誌第一個字段記錄的並不是客戶端IP(10.0.0.61),而是反向代理服務器本身的IP(10.0.0.6);而很多時候,運維可能需要通過訪問日誌的用戶IP來統計用戶的訪問情況,如何解決這個問題呢?
添加以下字段即可

proxy_set_header X-Forwarded-For  $remote_addr;
位置:http,server,location

反向代理時,節點服務器獲取用戶真實IP的必要功能配置
在反向代理請求後端節點服務器的請求頭中增加獲取的客戶端IP的字段信息,然後節點後端可以通過程序或者相關的配置接收X-Forwared-For傳過來的用戶真實IP的信息。
web訪問日誌格式也得支持
配置nginx.conf配置文件中的log_format參數(http的Log模塊)
訪問日誌顯示X-Forward-For字段的用戶真實IP
web日誌格式配置如下

log_format  main  ‘$remote_addr - $remote_user [$time_local] "$request" ‘
                  ‘$status $body_bytes_sent "$http_referer" ‘
                  ‘"$http_user_agent" "$http_x_forwarded_for"‘;
access_log  logs/access.log  main;
#位置:http,server,location

參考資料:http://nginx.org/en/docs/http/ngx_http_log_module.html

測試效果
10.0.0.6 - - [13/Jun/2018:21:47:59 +0800] "GET / HTTP/1.0" 200 10 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "10.0.0.61"
最後一個字段就是客戶端的IP

Nginx實現反向代理負載均衡功能