Nginx正反向代理與負載均衡配置


By. 承祥君

系統環境:

平台:VMwear fusion For MAC

系統:CentOS release 6.5 (Final)

實驗時間:2017-10-15

 

實驗環境: 

IP對應的機器名:

圖示名              真正實驗主機名

Client A:           CCTV-1 (主機名)

Nginx Server:    CCTV-2 (主機名)

Web 1:             CCTV-3 (主機名)

Web 2:            CCTV-4 (主機名)

實驗開始:


 

一、正向代理

概念這里不介紹,可以參考http://my.oschina.net/yoyoko/blog/147414。

 

1.1 環境介紹

1.2 配置介紹

 

 

 [root@CCTV-2 ~]# cat /usr/local/nginx/nginx.conf

 1     server {
 2         listen       80;
 3         server_name  172.16.1.20;
 4         #charset koi8-r;
 5         #access_log  logs/host.access.log  main;
 6      resolver 114.114.114.114  #這里是DNS,訪問外網
 7         location / {
 8                 proxy_pass http://$http_host$request_uri;  # $http_host和$request_uri是nginx系統變量,不需要替換,保持原樣
10         #    root   html;
11         #    index  index.html index.htm;
12

Nginx client:

只有一個內網網卡,通過訪問Nginx server去訪問internet,其實翻牆、肉雞、之類的俗稱就是這個原理。

[root@CCTV-1 ~]# wget http://www.baidu.com
--2017-10-16 03:14:27--  http://www.baidu.com/
Resolving www.baidu.com... failed: Name or service not known.
wget: unable to resolve host address “www.baidu.com”


[root@CCTV-1 ~]# export http_proxy=http://172.16.1.20:80

[root@CCTV-1 ~]#  wget www.baidu.com      #可以成功訪問百度了  
--2017-10-16 03:14:35--  http://www.baidu.com/  
正在連接 10.0.0.136:80... 已連接。  
已發出 Proxy 請求,正在等待回應... 200 OK  
長度:未指定 [text/html]  
正在保存至: “index.html.1”  
  
    [ <=>                                                  ] 99,762      --.-K/s   in 0.07s  
  
2017-10-16 03:14:37 (1.36 MB/s) - “index.html.1” 已保存 [99762] 

 

二、反向代理 

 

2.1 環境介紹

 

2.2 配置介紹

[root@CCTV-2 conf.d]# cat nginx.conf   
server {  
    listen       80;  
    server_name  172.16.1.20; #根據環境介紹,nginx server ip  
  
    location / {  
           proxy_pass http://192.168.8.30; #被代理的服務器ip  
                }  
  
#proxy_pass: proxy_pass URL  
#默認值:NO  
#使用字段:location,location中的if字段  
#這個參數設置被代理服務器的地址和被映射的URL,地址可以使主機名、域名、IP加端口的模式,如:  
#proxy_pass    http://192.168.8.30:8099/second/;  
  
[root@CCTV-2 conf.d]#  ./usr/local/nginx/nginx -s reload #重啟加載配置 

看下結果:#先登錄到實驗環境中的clinet機上,ip如下:  

[root@CCTV-1 ~]# ifconfig                           
eth0      Link encap:Ethernet  HWaddr 08:00:27:3D:40:40  
          inet addr:172.16.1.10  Bcast:10.255.255.255  Mask:255.0.0.0  
          inet6 addr: fe80::a00:27ff:fe3d:4040/64 Scope:Link  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1  
          RX packets:2618345 errors:0 dropped:0 overruns:0 frame:0  
          TX packets:247926 errors:0 dropped:0 overruns:0 carrier:0  
          collisions:0 txqueuelen:1000  
          RX bytes:336182790 (320.6 MiB)  TX bytes:35145157 (33.5 MiB)  
  
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0  
          inet6 addr: ::1/128 Scope:Host  
          UP LOOPBACK RUNNING  MTU:16436  Metric:1  
          RX packets:177352 errors:0 dropped:0 overruns:0 frame:0  
          TX packets:177352 errors:0 dropped:0 overruns:0 carrier:0  
          collisions:0 txqueuelen:0  
          RX bytes:26547640 (25.3 MiB)  TX bytes:26547640 (25.3 MiB)  
  
[root@CCTV-1 ~]# curl 172.16.1.20    #訪問反向代理服務器  
<html>  
welcome to 192.168.8.30!!                   
</html>  
#我們看到訪問代理服務器,結果被轉發到了Web 1上。  
  
#接下來我們分別看下nginx-server和Web 1的日志:  

nginx-server:
[root@CCTV-2
~]# tail /usr/local/nginx/logs/access.log

172.16.1.10 - - [16/Oct/2017:02:25:57 +0800] "GET / HTTP/1.1" 200 46 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

  
web-server:  

[root@CCTV-3 ~]# tail -f /var/log/httpd/access_log
172.16.1.10</span> - - [16/Oct/2017:02:25:30 +0800] "GET / HTTP/1.0" 200 46 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

  
##我們看到nginx-server上的nginx的日志,顯示訪問的用戶是我們環境的clinet,  
#而web-1上顯示的ip是是nginx-server。  
#說白了反向代理,對客戶來說nginx-server就是真正的服務器,實際上,當用戶訪問nginx-server的時候,會將請求轉發到  
#web-1上,然后web-1將請求的結果發給nginx-server,然后由nginx-server將請求的結果轉交給用戶。  
  
#在web-server上看到的都是代理的ip,能不能也看到真實用戶的ip呢?  
  
[root@CCTV-2 conf.d]# cat nginx.conf                  
server {  
    listen       80;  
    server_name  172.16.1.20;                            #根據環境介紹,nginx server ip  
  
    location / {  
           proxy_pass http://192.168.8.30;                #被代理的服務器ip  
           proxy_set_header  X-Real-IP  $remote_addr;    #多了這行  
                 }  

 

[root@CCTV-2 ]# ./nginx -s reload

[root@CCTV-3 ~]# tail /var/log/httpd/access_log  
192.168.8.20 - - [15/Oct/2017:16:10:53 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7  
(x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"  
  
#改了之后還是顯示的是代理服務器的ip,我們去web-server上修改下配置  
[root@CCTV-3 ~]# vim /etc/httpd/conf/httpd.conf  
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined  
LogFormat "%h %l %u %t \"%r\" %>s %b" common  
LogFormat "%{Referer}i -> %U" referer  
LogFormat "%{User-agent}i" agent  
  
#修改為:(%h指的的訪問的主機,現在改為訪問的真實主機ip)  
LogFormat "%{X-Real-IP}i</span> %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined  
LogFormat "%h %l %u %t \"%r\" %>s %b" common  
LogFormat "%{Referer}i -> %U" referer  
LogFormat "%{User-agent}i" agent</span> 

 

[root@CCTV-3 ~]# service httpd restart  
停止 httpd:                                               [確定]  
正在啟動 httpd:                                           [確定]  
  
[root@CCTV-3 ~]# tail /var/log/httpd/access_log  
172.16.1.10 - - [15/Oct/2017:16:10:53 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7  
(x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"  
<span style="color:#FF0000;">10.0.0.139</span> - - [08/Jun/2016:16:16:01 +0800] "GET / HTTP/1.0" 200 26 "-" "curl/7.19.7  
(x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"  
#已經變成了真實的訪問地址  

 

2.3 代理多個WEB服務器:

[root@CCTV-2 conf.d]# cat nginx.conf  
server {  
    listen       80;  
    server_name  172.16.1.20;  
  
    location / {  
           proxy_pass http://192.168.1.30;  
           proxy_set_header  X-Real-IP  $remote_addr;  
                }  
    location /web2 {                            #多加個location  
           proxy_pass http://192.168.1.40/;  #注意末尾多了一個"/",詳細請參考我另一篇文章“Nginx的4種配置”
           proxy_set_header  X-Real-IP  $remote_addr;      
                }  

#我們去client上訪問試試:  
[root@CCTV-1 ~]# curl 172.16.1.20
<html>  
192.168.8.30  
</html>  
#訪問成功  

[root@clint ~]# curl 172.16.1.20/web2
<html>  
192.168.8.40
</html>  
#訪問成功  

 

三、負載均衡

負載均衡實現的方式有很多,常用的lvs四層負載均衡,nginx是七層負載均衡,可以網上查詢相關資料。

3.1 環境介紹

3.2 配置介紹

1.upstream是Nginx的HTTP Upstream模塊,這個模塊通過一個簡單的調度算法來實現客戶端IP到后端服務器的負載均衡。在上面的設定中,通過upstream指令指定了一個負載均衡器的名稱1.2.3.4。這個名稱可以任意指定,在后面需要用到的地方直接調用即可。

 

2.Nginx的負載均衡模塊目前支持4種調度算法,下面進行分別介紹,其中后兩項屬於第三方調度算法。  

  • 輪詢(默認)。每個請求按時間順序逐一分配到不同的后端服務器,如果后端某台服務器宕機,故障系統被自動剔除,使用戶訪問不受影響。Weight 指定輪詢權值,Weight值越大,分配到的訪問機率越高,主要用於后端每個服務器性能不均的情況下。

  • ip_hash。每個請求按訪問IP的hash結果分配,這樣來自同一個IP的訪客固定訪問一個后端服務器,有效解決了動態網頁存在的session共享問題。

  • fair。這是比上面兩個更加智能的負載均衡算法。此種算法可以依據頁面大小和加載時間長短智能地進行負載均衡,也就是根據后端服務器的響應時間來分配請求,響應時間短的優先分配。Nginx本身是不支持fair的,如果需要使用這種調度算法,必須下載Nginx的upstream_fair模塊。

  • url_hash。此方法按訪問url的hash結果來分配請求,使每個url定向到同一個后端服務器,可以進一步提高后端緩存服務器的效率。Nginx本身是不支持url_hash的,如果需要使用這種調度算法,必須安裝Nginx 的hash軟件包。

3.upstream 支持的狀態參數

在HTTP Upstream模塊中,可以通過server指令指定后端服務器的IP地址和端口,同時還可以設定每個后端服務器在負載均衡調度中的狀態。常用的狀態有:      

  • down,表示當前的server暫時不參與負載均衡。

  • backup,預留的備份機器。當其他所有的非backup機器出現故障或者忙的時候,才會請求backup機器,因此這台機器的壓力最輕。

  • max_fails,允許請求失敗的次數,默認為1。當超過最大次數時,返回proxy_next_upstream 模塊定義的錯誤。

  • fail_timeout,在經歷了max_fails次失敗后,暫停服務的時間。max_fails可以和fail_timeout一起使用。

注,當負載調度算法為ip_hash時,后端服務器在負載均衡調度中的狀態不能是weight和backup。

我們來看下具體配置: 

[root@CCTV-2 ]# cat nginx.conf  
http {  
    include       /etc/nginx/mime.types;  
    default_type  application/octet-stream;  
  
    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  /var/log/nginx/access.log  main;  
  
    sendfile        on;  
    #tcp_nopush     on;  
  
    keepalive_timeout  65;  
  
    #gzip  on;  
upstream HZ.COM {  
    server 192.168.8.30:80;  
    server 192.168.8.40:80;  
    }  
    include /etc/nginx/conf.d/*.conf;  
}  
  

    location / {   
         proxy_pass http://HZ.COM; proxy_set_header X-Real-IP $remote_addr;   
               }  
#注,upstream是定義在server{ }之外的,不能定義在server{ }內部。定義好upstream之后,用proxy_pass引用一下即可。  

 

4.測試結果

[root@CCTV-1 ~]# curl 172.16.1.20
<html>  
192.168.8.30  
</html>  
[root@CCTV-1 ~]# curl 172.16.1.20
<html>  
192.168.8.40 
</html>  
[root@CCTV-1 ~]# curl 172.16.1.20
<html>  
192.168.8.30  
</html>  
#結果是Web1,2交替出現,說明默認是輪詢方式的負載均衡。  

 

5.健康檢查

一般健康檢查都需要搞個keepalived,但nginx也有相應的參數可以設置。

  • max_fails,允許請求失敗的次數,默認為1。當超過最大次數時,返回proxy_next_upstream 模塊定義的錯誤。

  • fail_timeout,在經歷了max_fails次失敗后,暫停服務的時間。max_fails可以和fail_timeout一起使用,進行健康狀態檢查。

[root@CCTV-2 ]# cat nginx.conf  
http {     
    include       /etc/nginx/mime.types;  
    default_type  application/octet-stream;  
  
    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  /var/log/nginx/access.log  main;  
  
    sendfile        on;  
    #tcp_nopush     on;  
  
    keepalive_timeout  65;  
  
    #gzip  on;  
    upstream HZ.COM {  
    server 192.168.8.30:80 weight=1 max_fails=2 fail_timeout=2;  
    server 192.168.8.40:80 weight=1 max_fails=2 fail_timeout=2;  
    }  
    include /etc/nginx/conf.d/*.conf;  
    }  
    
[root@CCTV-2 ]# nginx -s reload

 

6.測試下結果

[root@CCTV-3 httpd]# service httpd stop  #關閉web-server1服務  

[root@CCTV-1 ~]# curl 172.16.1.20  
<html>  
192.168.8.40
</html>  

[root@CCTV-1 ~]# curl 172.16.1.20  
<html>  
192.168.8.40
</html>  

#現在只能訪問web-server2了。  
  
[root@CCTV-3 httpd]# service httpd start   #打開web-server1服務  

[root@CCTV-1 ~]# curl 172.16.1.20  
<html>  
192.168.8.30
</html>  

[root@CCTV-1 ~]# curl 172.16.1.20  
<html>  
192.168.8.40
</html>  

[root@CCTV-1 ~]# curl 172.16.1.20  
<html>  
192.168.8.30
</html>  

7.ip_hash的負載均衡

[root@CCTV-2 ]# cat nginx.conf  
upstream HZ.COM {  
    ip_hash;  
    server 192.168.8.30:80 weight=1 max_fails=2 fail_timeout=2;  
    server 192.168.8.40:80 weight=1 max_fails=2 fail_timeout=2;  
    }  
[root@CCTV-2 ]# ]# ./nginx -s reload  
  
[root@CCTV-1 ~]# curl 172.16.1.20 
<html>  
192.168.8.30
</html>  

[root@CCTV-1 ~]# curl 172.16.1.20 
<html>  
192.168.8.30
</html>  
#配置這種負載均衡后,>每個請求按訪問IP的hash結果分配,這樣來自同一個IP的訪客固定訪問一個后端服務器,  
#有效解決了動態網頁存在的session共享問題。(一般電子商務網站用的比較多)  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM