1. 程式人生 > >【第七課】Nginx反向代理和負載均衡

【第七課】Nginx反向代理和負載均衡

功能 次數 curl ati clu stream clas 負載均衡集群 是什麽

目錄

  • 一、Nginx負載均衡集群 介紹
  • 二、實現一個簡單的負載均衡
  • 三、Nginx負載均衡組件介紹
  • 四、Nginx負載均衡實際應用

一、Nginx負載均衡集群 介紹

  負載均衡(Load Balance)集群提供了一種行之有效的辦法,來擴展網絡設備和服務器負載、帶寬和吞吐量,同時加強了網絡數據處理能力,提供了網絡的靈活性和可用性。

  Nginx的負載均衡組件主要有2個:

ngx_http_proxy_module:proxy代理模塊,用於把請求後端拋給服務器節點或upstream服務器池。

ngx_http_upstream_module:負載均衡模塊,可以實現網站的負載均衡功能和幾點的健康檢查。

二、實現一個簡單的負載均衡

(1)環境介紹

    站點訪問                    訪問主頁                    IP地址             角色
192.168.56.110:8081        welcome to bbs.abc.org        192.168.56.110        web1
192.168.56.111:8082        welcome to blog.abc.org       192.168.56.111        web2
www.abc.org                        無                     192.168.56.11        負載均衡

(2)配置bbs和blog站點並測試訪問

[root@localhost vhosts]# vim bbs.abc.org.conf 
server {
        listen 8081;
        server_name 192.168.56.110;
        root /vhosts/html/bbs;
        index index.html index.htm index.php;
}
[root@localhost vhosts]# vim blog.abc.org.conf
server {
        listen 8082;
        server_name 192.168.56.111;
        root /vhosts/html/blog;
        index index.html index.htm index.php;
}
[root@localhost vhosts]# curl 192.168.56.110:8081
welcome to bbs.abc.org
[root@localhost vhosts]# curl 192.168.56.111:8082
welcome to blog.abc.org

(3)配置負載均衡

[root@localhost vhosts]# cat www.abc.org.conf 
upstream web_server{      //配置負載均衡池
    server 192.168.56.110:8081 weight=1;
    server 192.168.56.111:8082 weight=1;
}
server {
    listen 80;
    server_name www.abc.org abc.org;
    root /vhosts/html/www;
    index index.html index.php index.htm;
    
    access_log logs/www.abc.org_access.log main;
    error_log logs/www.abc.org_error.log info;    
    
    location /{
        proxy_pass http://web_server;  //反向代理到負載均衡池
    }
    
    location ~ \.php$ {
            root           /vhosts/html/www;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }


}
[root@localhost vhosts]# nginx -t
nginx: the configuration file /usr/local/nginx1.15.1/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx1.15.1/conf/nginx.conf test is successful
[root@localhost vhosts]# nginx -s reload
[root@localhost vhosts]# curl www.abc.org  //測試訪問是否實現輪詢bbs和blog
welcome to bbs.abc.org
[root@localhost vhosts]# curl www.abc.org
welcome to blog.abc.org
[root@localhost vhosts]# curl www.abc.org
welcome to bbs.abc.org
[root@localhost vhosts]# curl www.abc.org
welcome to blog.abc.org

三、Nginx負載均衡組件介紹

1、upstream模塊

  Nginx的負載均衡功能依賴於ngx_http_upstream_module模塊,可支持代理的方式有:proxy_pass、fastcgi_pass、memcached_pass等。該模塊允許Nginx定義一組或多組節點服務器組,使用時,通過proxy_pass代理方式把網站的請求發送到實現定義好的upstream組的名稱上,具體的格式為"proxy_pass http://web_server_pools",其中web_server_pools為upstream節點服務器組名稱。下面舉例說明:

upstream web_server{
    server 192.168.56.110:8081 weight=1 max_fails=1 fail_timeout=10s;
    server 192.168.56.111:8082 weight=1 max_fails=1 fail_timeout=10s;
   server 192.168.56.112:8083 weight=1 max_fails=1 fail_timeout=10s backup;
   server 192.168.56.113:8084 weight=1 max_fails=1 fail_timeout=10s down;
}

upstream參數說明:
server 192.168.56.110:8081  表示的是負載均衡後端的RS配置,可以是IP或者域名,如果端口不寫,默認為80端口,高並發場景下,IP可以換成域名,通過DNS做負載均衡
weight=1  代表服務器的權重,默認為1。權重數字越大表示接受的請求比例越大
max_fails=1  表示Nginx嘗試連接後端主機失敗的次數,這個值是配置proxy_next_upstream、fastcgi_next_upstream和memcached_next_upstream這3個參數使用,當Nginx接收後端服務器返回這3個參數定義的狀態碼時,會把這個請求轉發給正常工作的後端RS
fail_timeout=10s  在max_fails定義的的失敗次數後,距離下一次檢查的時間間隔,默認為10s
backup  熱備配置(RS節點高可用)表示這個服務器作為備份服務器,當主服務器全部宕機,就會向這個服務器轉發請求
down  表示該服務器永遠不可用,這個參數可以配合ip_hash使用

2、upstream的調度算法

  調度算法一般分為2類,一種是靜態調度算法,例如:rr、wrr、ip_hash等,負載均衡器根據自身設定的規則進行分配,不考慮後端節點服務器的情況。

  一種是動態調度算法,例如least_conn、fair等,負載均衡器會根據後端節點服務器的當前狀態來決定是否分發請求。

  (1)rr輪詢(默認調度算法,靜態調度算法)

  按客戶端請求順序依次將客戶端的請求逐一分配到不同的後端服務器節點,和LVS的rr算法一樣,如果後端節點服務器宕機,宕機的服務器會從服務器池中剔除,保證用戶訪問的正常。

  (2)wrr(權重輪詢,靜態調度算法)

  在rr輪詢的基礎上增加權重,使用該算法時,權重和用戶訪問成比例,權重越大,請求數越多。

  (3)ip_hash(靜態調度算法)

  每個請求按照客戶端的ip的hash結果分配,當新的請求到達,先將客戶端IP通過哈希算法哈希出一個值,在隨後的客戶端請求中,客戶的IP哈希值只要相同,就會被分配到同一臺服務器上。該調度算法可以解決動態網頁的session共享問題,但也會導致請求分配不均勻。需要註意的是當負載均衡調度算法為ip_hash時,後端服務器在負載均衡調度中的狀態不能使用weight和backup,即使配置了也不會生效。

  (4)fair(動態調度算法)

  該算法會根據後端服務器的響應時間來分配請求,響應時間較短的有限分配。這種算法更加的智能,可以根據頁面大小和加載時長智能地進行負載均衡。Nginx本身不支持fair調度算法,如果需要使用這種算法,需要下載Nginx的相關模塊upstream_fair

  (5)least_conn

  該算法會根據後端節點的連接數來決定分配請求,哪個機器的連接數少就優先分配。

  (6)url_hash算法

  根據訪問的URL的hash結果來分配請求,讓每個URL定向到同一個後端服務器,後端服務器為緩存服務器時效果顯著,可以提高後端緩存服務器的命中率。Nginx本身不支持這種算法,需要安裝hash模塊軟件包。

3、http_proxy_module模塊和參數

  proxy_pass指令屬於ngx_http_proxy_module模塊,此模塊可以將請求轉發到另一臺服務器上,在實際的反向代理中,會通過location功能匹配指定的URI,然後把符合匹配規則的URI請求通過proxy_pass指向定義好的upstream池。

  http_proxy模塊的相關參數:

proxy_set_header    設置http請求header項傳給後端服務器節點,例如:可以實現讓代理後端的服務器節點獲取訪問客戶端用戶的真是ip地址
client_body_buffer_size        用於指定客戶端請求主題緩沖區大小
proxy_connect_timeout        表示反向代理和後端節點服務器連接的超時時間,即發起三次握手等候響應的超時時間
proxy_send_timeout            表示代理後端服務器的數據回傳時間,即在規定時間內後端服務器必須傳完所有數據,否則,Nginx將會斷開連接
proxy_read_timeout            設置Nginx從代理的後端服務器獲取信息的時間,表示連接建立成功後,Nginx等待後端服務器的響應時間,其實是Nginx已經進入了後端的排隊之中等待處理的時間
proxy_buffer_size            設置緩沖區大小,默認該緩沖區大小等於指令proxy_buffers設置的大小
proxy_buffers                設置緩沖區的數量和大小。Nginx從代理的後端服務器獲取的響應信息,會放置到緩沖區
proxy_busy_buffers_size        用於設置系統繁忙時期可以使用的proxy_buffers大小,推薦大小為proxy_buffers*2
proxy_temp_file_write_size    指定proxy緩存臨時文件的大小

舉個簡單的反向代理的例子:

[root@localhost vhosts]# !vim
vim www.abc.org.conf 
server {
        listen 80;
        server_name www.abc.org abc.org;
        root /vhosts/html/www;
        index index.html index.php index.htm;

        access_log logs/www.abc.org_access.log main;
        error_log logs/www.abc.org_error.log debug;
        location /bbs {    
                proxy_pass http://192.168.56.110:8081/;  //配置當訪問www.abc.org/bbs時,反向代理到192.168.56.110:8081這臺服務器上
        }

        location ~ \.php$ {
            root           /vhosts/html/www;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
}
[root@localhost ~]# curl http://www.abc.org/bbs    //測試訪問
welcome to bbs.abc.org

四、Nginx負載均衡實際應用

1、環境說明

主機名 IP地址 角色說明
web01 192.168.56.12 nginx web01服務器
web02 192.168.56.13 nginx web02服務器
lb 192.168.56.11 nginx負載均衡器

2、Nginx反向代理負載均衡實踐

(1)在web01和web02上yum安裝nginx,並同樣修改nginx.conf

[root@web01 ~]# yum install -y nginx
[root@web02 ~]# yum install -y nginx
[root@web01 ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    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;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        server_name  bbs.abc.org;
        root         /application/html/bbs;
    index index.php index.html index.htm;
    }

    server {
    listen 80;
    server_name www.abc.org;
    root    /application/html/www;
    index index.php index.html index.htm;
    }
}

(2)配置web01和web02的host解析

[root@web01 ~]# cat /etc/hosts
192.168.56.12  bbs.abc.org www.abc.org
[root@web02 ~]# cat /etc/hosts
192.168.56.13  bbs.abc.org www.abc.org

(3)配置主頁index.html,並測試訪問

root@web01 ~]# mkdir /application/html/{www,bbs} -pv
[root@web01 ~]# echo "welcome to use bbs.abc.org 12" > /application/html/bbs/index.html
[root@web01 ~]# echo "welcome to use www.abc.org 12" > /application/html/www/index.html
[root@web02 ~]# mkdir /application/html/{www,bbs} -pv
[root@web02 ~]# echo "welcome to use bbs.abc.org 13" > /application/html/bbs/index.html
[root@web02 ~]# echo "welcome to use www.abc.org 13" > /application/html/www/index.html
[root@web01 ~]# curl www.abc.org
welcome to use www.abc.org 12
[root@web01 ~]# curl bbs.abc.org
welcome to use bbs.abc.org 12
[root@web02 ~]# curl www.abc.org
welcome to use www.abc.org 13
[root@web02 ~]# curl bbs.abc.org
welcome to use bbs.abc.org 13

(4)配置負載均衡器

[root@lb vhosts]# vim www.abc.org.conf 
upstream web_server{
        server 192.168.56.12:80 weight=1;
        server 192.168.56.13:80 weight=1;
}
server {
        listen 80;
        server_name www.abc.org abc.org;
        root /vhosts/html/www;
        index index.html index.php index.htm;

        access_log logs/www.abc.org_access.log main;
        error_log logs/www.abc.org_error.log debug;

        location /{
                proxy_pass http://web_server;
        }
}
[root@lb vhosts]# nginx -t
nginx: the configuration file /usr/local/nginx1.15.1/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx1.15.1/conf/nginx.conf test is successful
[root@lb vhosts]# nginx -s reload

(5)lb上綁定hosts解析,測試訪問

[root@localhost vhosts]# cat /etc/hosts
192.168.56.11 www.abc.org bbs.abc.org 
[root@lb vhosts]# curl www.abc.org
welcome to use bbs.abc.org 12
[root@lb vhosts]# curl www.abc.org
welcome to use bbs.abc.org 13

  從上面的測試結果可以看到,正常地實現了反向代理和負載均衡,但是細致地看一看,發現在訪問www.abc.org時,返回的的結果是welcome to use bbs.abc.org 12以及welcome to use bbs.abc.org 13,和我們想要訪問到的結果:welcome to use www.abc.org 12以及welcome to use www.abc.org 13大相徑庭,完全不一致!!這又是什麽原因呢?

  在配置虛擬主機時,在web01和web02分別配置了2個虛擬主機,一個是bbs.abc.org,一個www.abc.org。bbs虛擬主機放在了前面,這點很重要。那麽當用戶訪問www.abc.org時,請求頭部攜帶了www.abc.org主機頭部請求Nginx的反向代理服務器,但是在反向代理服務器向後端服務器web01或web02重新發起請求時,默認並沒有在請求頭部信息告訴web01或web02要請求的是哪臺虛擬主機。所以,web服務器接收到請求後發現並沒有主機頭信息,因此web01或web02就直接將第一個虛擬主機(bbs.abc.org)發給了反向代理服務器了。

  那麽這問題又該如何解決呢?就是當反向代理向後端服務器發起請求時,要攜帶主機頭信息,以明確指明需要訪問的虛擬主機。具體配置也簡單,增加一行如下配置即可:

proxy_set_header Host $host;

  在代理向後端發送請求時,在http請求頭部加入了host字段信息後,如果後端配置了多個虛擬主機,它就可以識別代理的是哪個虛擬主機。重新配置後,訪問如下:

[root@localhost vhosts]# vim www.abc.org.conf 
upstream web_server{
        server 192.168.56.12:80 weight=1;
        server 192.168.56.13:80 weight=1;
}
server {
        listen 80;
        server_name www.abc.org abc.org;
        root /vhosts/html/www;
        index index.html index.php index.htm;

        access_log logs/www.abc.org_access.log main;
        error_log logs/www.abc.org_error.log debug;

        location /{
                proxy_set_header Host $host;
                proxy_pass http://web_server;
        }
}
[root@localhost vhosts]# nginx -t
nginx: the configuration file /usr/local/nginx1.15.1/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx1.15.1/conf/nginx.conf test is successful
[root@localhost vhosts]# nginx -s reload
[root@localhost vhosts]# curl www.abc.org
welcome to use www.abc.org 12
[root@localhost vhosts]# curl www.abc.org
welcome to use www.abc.org 13

  可以看到最後的返回結果為:welcome to use www.abc.org 12以及welcome to use www.abc.org 13,這就是proxy_set_header參數的作用。

3、反向代理後後端服務器記錄用戶真實IP

  在反向代理實現後,在windows客戶端做hosts解析,並訪問,在web01或web02上查看訪問日誌,如下:

[root@web01 ~]# cat /var/log/nginx/www.abc.org_access.log 
192.168.56.11 - - [20/Jul/2018:05:51:53 -0400] "GET / HTTP/1.0" 200 30 "-" "curl/7.29.0"
192.168.56.12 - - [20/Jul/2018:05:52:50 -0400] "GET / HTTP/1.1" 200 30 "-" "curl/7.29.0"
192.168.56.11 - - [20/Jul/2018:05:53:17 -0400] "GET / HTTP/1.0" 200 30 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36"
192.168.56.11 - - [20/Jul/2018:05:53:40 -0400] "GET / HTTP/1.0" 200 30 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36"

可以看到對應的www.abc.org虛擬主機的訪問日誌記錄的並不是客戶端ip,而是反向代理服務器的ip,那麽如何獲取用戶的真是ip呢?其實只需要增加以下參數即可:

 proxy_set_header X-Forwarded-For $remote_addr;
表示在代理向後端服務器發送的http請求頭中加入X-Forwarded-For字段信息,用於後端服務器程序、日誌等接收記錄真實用戶的ip,而不是代理服務器的ip。在使用反向代理時,節點服務器獲取用戶真實ip的必要配置。
[root@localhost vhosts]# !vim  //修改負載均衡器的配置
vim www.abc.org.conf 
upstream web_server{
        server 192.168.56.12:80 weight=1;  //此處刪除了web02,作為測試機訪問
}
server {
        listen 80;
        server_name www.abc.org abc.org;

        location /{
                proxy_pass http://web_server;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;  //配置記錄真實ip

        }
}
[root@web02 nginx]# curl www.abc.org  //在web02上配置hosts解析訪問www.abc.org 
welcome to use www.abc.org 12
[root@web01 ~]# tail -2 /var/log/nginx/www.abc.org_access.log
192.168.56.11 - - [20/Jul/2018:23:20:52 -0400] "GET / HTTP/1.0" 200 30 "-" "curl/7.29.0" "192.168.56.13"
192.168.56.11 - - [20/Jul/2018:23:21:45 -0400] "GET /index.html HTTP/1.0" 200 30 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36" "192.168.56.1"

配置完成後,重載訪問,查看web01上的日誌可以看到,第一段表示的是$remote_addr,屬於代理服務器的ip,而最後一行才是用戶的真是ip記錄。

【第七課】Nginx反向代理和負載均衡