nginx的反向代理以及負載均衡模塊的使用

內容:

1、何爲代理

2、nginx的反向代理模塊以及使用

3、nginx的負載均衡模塊以及使用


一、何爲代理

代理,由字面意思可以理解爲代爲服務的是意思。

代理服務技術是一門很古老的技術,是在互聯網早期出現就使用的技術。一般實現代理技術的方式就是在服務器上安裝代理服務軟件,讓其成爲一個代理服務器,從而實現代理技術。常用的代理技術分爲正向代理、反向代理。

正向代理:

正常的用戶訪問站點是客戶打開瀏覽器,然後輸入相關的網站進行瀏覽,其實這就是一個代理的行爲,只不過代理的是瀏覽器,我們通過瀏覽器來代理請求站點服務,而正向代理服務器可以理解爲:

 wKioL1gTSg-SOQTFAAEt2yIdqGI777.png

反向代理:反向代理正好與正向代理相反,對於客戶端而言代理服務器就像是原始服務器,並且客戶端不需要進行任何特別的設置。客戶端向反向代理的命名空間(name-space)中的內容發送普通請求,接着反向代理將判斷向何處(原始服務器)轉交請求,並將獲得的內容返回給客戶端。 

wKiom1gTSh-REsOzAAEbezfcntc760.png

所以,nginx由於起輕量高效的特性,是的其成爲了反向代理服務器的熱門選擇。

二、ngixn的反向代理模塊以及使用

ngx_http_proxy_module模塊:

1、proxy_pass URL;

Context: location, if in location, limit_except

(1)注意:proxy_pass後面的路徑不帶uri時,其會將location的uri傳遞給後端主機;

server {

...

server_name HOSTNAME;

location /uri/ {

proxy http://hos[:port];

}

...

}

效果:http://HOSTNAME/uri --> http://host/uri

 

(2)proxy_pass後面的路徑是一個uri時,其會將location的uri替換爲proxy_pass的uri;

server {

...

server_name HOSTNAME;

location /uri/ {

proxy http://host/new_uri/;

}

...

}

效果:http://HOSTNAME/uri/ --> http://host/new_uri/

(3)如果location定義其uri時使用了正則表達式的模式,則proxy_pass之後必須不能使用uri; 用戶請求時傳遞的uri將直接附加代理到的服務的之後;

server {

...

server_name HOSTNAME;

location ~|~* /uri/ {

proxy http://host;

}

...

}

效果:http://HOSTNAME/uri/ --> http://host/uri/;

2、proxy_set_header field value;設定發往後端主機的請求報文的請求首部的值;Context: http, server, location,常用於標記客戶端的真是IP地址

例:

proxy_set_header X-Real-IP  $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

3、proxy_cache_path:定義可用於proxy功能的緩存;Context: http

proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_

4、proxy_cache zone | off;

指明要調用的緩存,或關閉緩存機制;Context: http, server, location

5、 proxy_cache_key string;

緩存中用於“鍵”的內容;

默認值:proxy_cache_key $scheme$proxy_host$request_uri;

6、proxy_cache_valid [code ...] time;

定義對特定響應碼的響應內容的緩存時長;

定義在http{...}中;

proxy_cache_path /var/cache/nginx/proxy_cache levels=1:1:1 keys_zone=pxycache:20m max_size=1g;

定義在需要調用緩存功能的配置段,例如server{...};

proxy_cache pxycache;

proxy_cache_key $request_uri;

proxy_cache_valid 200 302 301 1h;

proxy_cache_valid any 1m;

7、proxy_cache_use_stale

proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...;

Determines in which cases a stale cached response can be used when an error occurs during communication with the proxied server.

8、proxy_cache_methods GET | HEAD | POST ...;

只有標記的相關請求方法才進行緩存

9、proxy_hide_header field;

By default, nginx does not pass the header fields “Date”, “Server”, “X-Pad”, and “X-Accel-...” from the response of a proxied server to a client. The proxy_hide_header directive sets additional fields that will not be passed.

10、proxy_connect_timeout time;

Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.

默認爲60s;

ngx_http_headers_module模塊  

    向由代理服務器響應給客戶端的響應報文添加自定義首部,或修改指定首部的值;  

    1、add_header name value [always];

    添加自定義首部;

  例:

    add_header X-Via  $server_addr;

    add_header X-Accel $server_name;

   

    2、expires [modified] time;

    expires epoch | max | off;

    用於定義Expire或Cache-Control首部的值;

下面來進行操作效果的演示:

規劃:nginx反代的服務IP:10.1.249.75,後端真實服務器IP:10.1.252.235

在ngixn服務器中配置:

修改ngixn的反向代理服務中的配置文件,啓動反向代理模式

   location / {
        #root   /usr/share/nginx/html;
        proxy_pass http://10.1.252.235;
        index  index.html index.htm;
    }
[root@localhost upload]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.1.249.75  netmask 255.255.0.0  broadcast 10.1.255.255
        inet6 fe80::20c:29ff:fe65:55a6  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:65:55:a6  txqueuelen 1000  (Ethernet)
        RX packets 9647  bytes 1463932 (1.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1736  bytes 231308 (225.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


在真實服務器中提供測試頁面:

[root@localhost html]# cat index.html 
RS1


在客戶端測試,已經成功訪問只後端服務器

[root@localhost ~]# curl 10.1.249.75
RS1
[root@localhost ~]# curl 10.1.249.75
RS1


查看真實服務器的訪問日誌,發現訪問的客戶段IP是代理服務器的IP:

[root@localhost html]# tail /var/log/httpd/access_log 
10.1.249.75 - - [28/Oct/2016:20:10:46 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:46 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:46 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:49 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"


有沒有辦法獲取真正的客戶端IP呢?答案是肯定的,nginx提供了自身的變量可以提取原始客戶的請求報文信息,只需要保留原客戶端的真實IP即可

修改nginx的配置文件,添加其中一條命令:proxy_set_header X-Real-IP $remote_addr;

   

location / {
        #root   /usr/share/nginx/html;
        proxy_pass http://10.1.252.235;
        proxy_set_header X-Real-IP $remote_addr;
        index  index.html index.htm;
    }
[root@localhost upload]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost upload]# nginx -s reload

            再次測試,並訪問日誌:

[root@localhost html]# tail /var/log/httpd/access_log 
10.1.249.75 - - [28/Oct/2016:20:10:46 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:49 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:16:01 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:16:04 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"


發現源IP還是沒有變,這是因爲httpd的配置文件定義了日誌的格式,只需要簡單修改日誌格式即可,講%h改爲之前nginx定義的報文首部{X-Real-IP}i

LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined


再次測試,並訪問日誌,已經能正確記錄遠端客戶的IP了!

[root@localhost html]# !tai
tail /var/log/httpd/access_log 
10.1.249.75 - - [28/Oct/2016:20:10:47 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:48 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:10:49 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:16:01 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.249.75 - - [28/Oct/2016:20:16:04 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.252.215 - - [28/Oct/2016:20:19:40 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.252.215 - - [28/Oct/2016:20:19:40 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
10.1.252.215 - - [28/Oct/2016:20:19:41 +0800] "GET / HTTP/1.0" 200 4 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"


三、nginx的負載均衡模塊以及使用

與lvs不同的是,nginx在應用層提供了強大的負載均衡的功能,並帶有後端服務的健康檢查功能。

nginx的負載均衡模塊怎麼使用?

ngx_http_upstream_module模塊 (定義在http上下文)

1、upstream name { ... }

定義後端服務器組,會引入一個新的上下文;Context: http

upstream httpdsrvs {

server ...

server...

...

}

2、server address [parameters];

在upstream上下文中server成員,以及相關的參數;Context: upstream

address的表示格式:

unix:/PATH/TO/SOME_SOCK_FILE

IP[:PORT]

HOSTNAME[:PORT]

parameters:

weight=number

權重,默認爲1;

max_fails=number

失敗嘗試最大次數;超出此處指定的次數時,server將被標記爲不可用;

fail_timeout=time

設置將服務器標記爲不可用狀態的超時時長;

max_conns

當前的服務器的最大併發連接數;

backup

將服務器標記爲“備用”,即所有服務器均不可用時此服務器才啓用;

down

標記爲“不可用”;

3、least_conn;

最少連接調度算法,當server擁有不同的權重時其爲wlc;

4、 ip_hash;

源地址hash調度方法;

5、hash key [consistent];

基於指定的key的hash表來實現對請求的調度,此處的key可以直接文本、變量或二者的組合;

作用:將請求分類,同一類請求將發往同一個upstream server;

示例:

hash $request_uri consistent;

hash $remote_addr;

6、keepalive connections;

爲每個worker進程保留的空閒的長連接數量;

下面來實驗驗證:

規劃:nginx反代的服務IP:10.1.249.75,後端服務器RS1:10.1.252.235,後端服務器RS2:10.1.252.215

(1)RS1,RS2啓動web服務,並提供相關的測試頁面

(2)配置nginx的負載均衡:

在httpd段添加:

   

upstream test {
    server 10.1.252.235;
    server 10.1.252.215;
}

(3)啓動反向代理模式,並實現負載均衡:

   

location / {
        #root   /usr/share/nginx/html;
        proxy_pass http://test;
        proxy_set_header X-Real-IP $remote_addr;
        index  index.html index.htm;
    }
[root@localhost upload]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost upload]# nginx -s reload

(4)客戶端測試,已經可以實現負載均衡功能(默認是輪詢rr算法):

[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS2
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS2
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS2
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS2


(5)添加權重測試:

 

  upstream test {
    server 10.1.252.235 weight=2;
    server 10.1.252.215;
}
[root@localhost ~]# curl http://10.1.249.75
RS2
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS2
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS2
[root@localhost ~]# curl http://10.1.249.75
RS1
[root@localhost ~]# curl http://10.1.249.75
RS1

(6)我們知道,lvs的負載均衡調度中,lvs自身並沒有對後端服務器進行健康狀態檢測的機制,也就是說後端服務器掛了還是會照樣進行調度,而ngixn則進行健康狀態檢查。修改配置如下:

 

  upstream test {
    server 10.1.252.235 max_fails=3 fail_timeout=10;
    server 10.1.252.215 max_fails=3 fail_timeout=10;
}

        (7)停掉RS1前的測試:

[root@localhost ~]# for i in `seq 10`;do curl http://10.1.249.75;done 
RS1
RS2
RS1
RS2
RS1
RS2
RS1
RS2
RS1
RS2

        (8)停掉RS1測試:

[root@localhost html]# service httpd stop
Stopping httpd:                                            [  OK  ]
[root@localhost html]# 
[root@localhost ~]# for i in `seq 10`;do curl http://10.1.249.75;done 
RS2
RS2
RS2
RS2
RS2
RS2
RS2
RS2
RS2
RS2

(9)已經自動把RS排除,現在再次恢復RS測試:

[root@localhost ~]# for i in `seq 10`;do curl http://10.1.249.75;done 
RS2
RS1
RS2
RS1
RS2
RS1
RS2
RS1
RS2
RS1


        好了nginx的反向代理和負載均衡功能就演示到這裏,更多文章請關注 我的博客


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章