1. 程式人生 > >nginx反向代理-後端服務器組設置

nginx反向代理-後端服務器組設置

web服務器 正向 local 請求方法 否則 字段 對組 網站 page

nginx服務器的反向代理時其最常用的重要功能之一,在實際工作中應用廣泛,涉及的配置指令也比較多。下面會盡量詳細地介紹對應的指令,及其使用狀態。

反向代理一般是互聯網需要向內網拉取資源,比如訪問一個web網站時,互聯網應用通過一個代理服務器到後面真實的web服務器拉取應用所需的數據。

nginx服務器反向代理用到的指令如果沒有特別的說明,原則上可以出現在nginx配置文件的http塊,server塊和location塊中,但是同正向代理一樣,一般是搭建在nginx服務器中單獨配置一個server塊用來設置代理服務。這些指令主要由ngx_http_proxy_module模塊進行解析和處理。該模塊是nginx服務器的標準http模塊。

nginx服務器支持設置一組服務器作為後端服務器,因此在說明nginx反向代理指令之前,首先說明nginx的後端服務器組的配置。

後端服務器組的指令,是由nginx標準模塊ngx_http_upstream_module進行解析和處理的。

後端服務器組的指令

1.upstream指令,該指令是設置後端服務器組的主要指令,其他指令都在該指令中進行配置。語法結構為

upstream  name {
      ......              #後端服務器設置

}

#其中name是後端服務器的組名。花括號中列出了後端服務器組中包含的服務器。

默認情況下,某個服務器組接收到請求後,按照輪叫調度策略順序選擇組內的服務器處理請求。如果一個服務器在處理請求過程中出現錯誤,則請求會被順序交給組內的下一個服務器處理,一直到返回正常響應。但是如果所有組內的服務器出錯,則返回最後一個服務器的處理結果。還可以在根據每個服務器的處理能力不同,給各個服務器配置不同的權重。權重的配置包含在server指令中。

2:server指令

該指令用於設置組內的服務器,語法結構為

server  address  [parameters];

#address: 服務器的地址,可以是包含端口號的ip地址,域名或者以“unix:”為前綴的用於進程間通信的套接字

#parameters: 為當前服務器的更多屬性,如下。
  • weight=number, 為組內的服務器設置權重,權重高的被優先用於請求處理。默認服務器權重為1.
  • max_fails=number, 設置請求失敗次數。在一定時間範圍內,當對組內某臺服務器請求失敗的次數超過該變量設置的值時,認為該服務器無效。默認是1,

若設置為0則不用上面的辦法檢查服務器是否有效、

  • fial_timeout=time;有兩個作用,一個是 設置 max_fails指令中“一定時間範圍”的時長,二是在檢查服務器是否有效時,如果一臺服務器被認為是無效的,

   該變量設置的時間為認為服務器無效持續的時間。在這個時間內不再檢查該服務器的狀態,並一直認為它是無效的。默認是10s。

  • backup: 將組內服務器標記為備用服務器,只有當正常的服務器處於無效(down)狀態或者繁忙(busy)狀態時,該服務器才被用來處理客戶請求。
  • down:將某臺服務器標記為永久無效狀態。

3: ip_hash指令,該指令用於實現會話保持功能,將某個客戶端的多次請求定向到組內同一臺服務器上,保證客戶端與服務器之間建立穩定的會話。只有當該服務器無效處於down狀態時,客戶端請求才會被下一個服務器接收和處理。

ip_hash;
ip_hash技術在一些情況下非常有用,能夠避免我們關心的服務組內各個服務器之間會話共享的問題。但是ip_hash技術在應用過程中是有限制的。
首先,ip_hash指令不能與server指令中的weight變量一起使用。其次,由於ip_hash技術主要根據客戶端的ip地址分配服務器,因此整個系統中,nginx服務器應該是處於最
前端的服務器,這樣才能獲取到客戶端的ip地址,同時還要註意客戶端的ip地址必須是C類地址。
upstream  backend
{
      ip_hash;
      server  www.test1.com;
      server  www.test2.com;       
}

如上一個實例,在添加ip_hash指令後,使用同一臺服務器發送請求,將會看到一只是test1在響應;如果註釋掉ip_hash,將會看到的是輪詢響應請求。

4.keepalive指令,該指令用於控制網絡連接保持功能。通過該指令,能夠保證nginx服務器工作進程為服務器組打開一部分網絡連接,並且將數量控制在一定範圍內。類似於進程池。

keepalive  connections;

#connections為nginx1服務器每一個工作進程運行服務器組保持的空閑網絡連接數的上限值。如果超過該值,工作進程將采用最近最少使用策略關閉網絡連接、

5:least_conn指令,該指令用於配置nginx服務器使用負載均衡的策略。該指令在功能上實現了最少連接負載均衡算法,在選擇組內的服務器時,考慮個服務器權重的同時,每次選擇的都是當前連接最少的那臺服務器,如果這樣的服務器有多臺,則選用加權輪叫原則選擇權重最大的服務器。

least_conn;

反向代理指令

nginx的反向代理指令有很多,這裏我們會詳細的介紹的!

1.proxy_pass指令,該指令用來設置被代理服務器的地址,可以是主機名稱,IP地址加端口號的形式。

proxy_padd  URL;

#其中,URL為要設置的被代理服務器的地址,包含傳輸協議,主機名稱或IP地址加端口號,uri等,傳輸協議通常是http或者https。也可以是unix開頭的套接字路徑。

若是被代理的是一組服務器,則需要使用upstream指令配置後端服務器組!

通過簡單的實例說明proxy_pass的用法!

#第一種僅代理一個服務器
        location / {

            proxy_pass http://10.0.102.214:8080;
        }
#第二種,代理一組服務器 upstream backend #需要註意的是upstream指令不能寫在server塊中 { server
10.0.102.214:8080; server 10.0.102.204:8080; } server { listen 80; server_name localhost; location / { proxy_pass http://backend; } }
##############################################
說明,之前有一種寫法是把http協議寫在upstream中,這樣在proxy_pass中不用寫http協議,但是我現在這樣的寫的話,檢查的時候總是會報錯!
upstream backend
{
server http://10.0.102.214:8080;
server http://10.0.102.204:8080;
}

server {
listen 80;
server_name localhost;


location / {

proxy_pass backend;
}
}

#這樣配置的時候總是會報錯,
[root@test1 conf]# nginx -t
nginx: [emerg] invalid host in upstream "http://10.0.102.214:8080" in /usr/local/nginx/conf/nginx.conf:37
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed

proxy_pass中url是否包含URI的處理方式:如果URL中包含了URI,nginx服務器會使用新的uri替代原來請求中的URI;如果URL中不包含URI,nginx服務器不會改變原地址請求的URI。

#URL中包含了URI的配置
location /first.html { root html; index index.html index.htm; proxy_pass http://10.0.102.214:8080/one.html; } ##看這個配置,URL中含有URI,那麽nginx服務器會改變原來請求中的URI!
[root@test1 logs]# curl http://localhost/first.html #訪問本機
111111111111111111
[root@test1 logs]# curl http://10.0.102.214:8080/one.html #後面代理服務器的one.html
111111111111111111
#上面兩個可以看到,通過代理訪問時,uri被nginx服務器改寫了!

#URL不包含URI的配置
location /first.html {
root html;
index index.html index.htm;
proxy_pass http://10.0.102.214:8080;
}

#可以看到如果URL中不含URI,則nginx服務器不會改寫請求中的URI。
[root@test1 logs]# curl http://localhost/first.html
This is the first page!
[root@test1 logs]# curl http://10.0.102.214:8080/first.html
This is the first page

2.proxy_hide_header與proxy_pass_hide

默認情況下,nginx服務器在發送響應報文時候,報文頭部不包含如“Date”,"Server","X-Accel"等來自被代理服務器的信息,但是也會發送一些與被代理服務器有關的信息。

proxy_hide_header  field;
#指令用於設置nginx服務器發送響應時,隱藏一些頭部信息。
proxy_pass_header;
#該指令可以設置哪些頭部信息被發送
上面的兩個指令均可在http塊,server塊或者location塊中進行配置

默認情況下,代理服務器不會發送後端服務器的server信息給客戶端,這裏我們設置代理服務器發送後端服務器的server信息給客戶端!

#當前做代理服務器的nginx版本為
[root@test1 logs]# nginx -v
nginx version: nginx/1.10.2
[root@test1 logs]# 
#後端服務器的nginx版本為
[root@test3 html]# nginx -v
nginx version: nginx/1.0.15
[root@test3 html]# 

配置如下:

        proxy_pass_header server;             #設置要發送的信息
        location /first.html {
            root   html;
            index  index.html index.htm;
            proxy_pass http://10.0.102.214:8080;
        }

#訪問對應的URL
[root@mgt01 ~]# curl http://10.0.102.179/first.html -I
HTTP/1.1 200 OK
Date: Sun, 16 Dec 2018 16:03:02 GMT
Content-Type: text/html
Content-Length: 24
Connection: keep-alive
Server: nginx/1.0.15 #可以看到發送的nginx服務器的版本為後端服務器的版本信息
Last-Modified: Sun, 16 Dec 2018 15:39:16 GMT
Accept-Ranges: bytes

#把配置文件中proxy_pass_header server; 註釋掉,訪問信息如下
[root@mgt01 ~]# curl http://10.0.102.179/first.html -I
HTTP/1.1 200 OK
Server: nginx/1.10.2 #這裏的版本信息為代理服務器的版本信息
Date: Sun, 16 Dec 2018 16:07:41 GMT
Content-Type: text/html
Content-Length: 24
Connection: keep-alive
Last-Modified: Sun, 16 Dec 2018 15:39:16 GMT
Accept-Ranges: bytes

3.proxy_pass_request_body與proxy_pass_request_headers指令

這兩個指令用於配置是否將客戶端請求的請求體和請求頭發送給後端服務器,語法結構如下:

proxy_pass_request_body   on | off;
proxy_pass_request_header   on | off;

#默認設置為開啟。

4:proxy_set_header指令,該指令可以更改nginx服務器接收到客戶端請求的請求頭消息,然後將新的請求頭發送給後端服務器。

proxy_set_header   field  value;

#field: 要更改的頭域
#value: 更改的值,支持文本,變量或者變量的組合

默認情況下,nginx 重新定義代理請求HostConnection中的兩個頭字段,並刪除了值為空字符串的頭字段。其中請求頭Host被設置為了變量$proxy_hostConnection被設定為close

proxy_set_header  Host  $http_host;             #將目前的host值填充為客戶端請求的host
proxy_set_header  Host   $proxy_host;           #將當前location塊的server_name填充到host頭域。
proxy_set_header  Host  $host:$$proxy_port;     #將當前location塊的server_name指令和listen指令值一起填充到host頭域

5:proxy_set_body指令

該指令可以更改nginx服務器接收到客戶端請求的請求體的信息,然後將新的請求體發送給後端服務器。

proxy_set_body value;

#value為更改的信息,支持使用文本,變量或者變量的組合。

6:proxy_bind指令。在配置了多個基於名稱或者基於ip主機的情況下,如果我們希望代理連接由指定的主機處理,就可以使用該指令進行配置。

proxy_bind  address;

#address為指定主機的ip地址。

7:proxy_connect_timeout指令

該指令配置nginx服務器以後端服務器嘗試建立連接的時間,

proxy_connect_timeout  time;

#time為設置的超時時間,默認是60s

8:proxy_read_timeout指令

該指令配置nginx服務器向後端被代理服務器發出read請求後,等待響應的超時時間。

proxy_read_timeout   time

#time為設置的超時時間,默認是60s

9:proxy_send_timeout指令

該指令配置nginx服務器向後端被代理服務器發出write請求後,等待響應的超時時間,

proxy_send_timeout  time;

#time為設置的超時時間,默認是60s

10:proxy_http_version指令

該指令用於配置nginx服務器提供代理服務的http版本,

proxy_http_version  1.0|1.1;

#默認是1.0版本。1.1版本支持upstream服務器組設置中的keepalive指令。

11.proxy_method指令

該指令用於設置nginx把請求發往後端服務器組時使用的請求方法,一般為POST或者GET。設置了該指令,客戶端的請求方法將被忽略。

proxy_method  method;

#其中,method的值可以設置為POST或者GET,註意不加引號。

12:proxy_ignore_client_abort指令

該指令用於設置在客戶端中斷網絡請求時,nginx服務器是否中斷對後端服務器的請求。

proxy_ignore_client_abort  on|off;
#默認設置為off,當客戶端中斷網絡請求時,nginx服務器中斷對後端服務器的請求

13:proxy_ignore_headers指令

該指令用於設置一些http響應頭域,nginx服務器接收到被代理服務器的響應數據後,不會處理被設置的頭域。

proxy_ignore_headers  field....;
#field為要設置的http響應頭,

14:proxy_redirect指令

該指令用於修改後端服務器返回的響應頭中的location頭域和refresh頭域,與proxy_pass指令配合使用。比如,nginx服務器通過proxy_pass指令將客戶端的請求地址重寫為被代理服務器的地址,那麽nginx服務器返回給客戶端的響應頭中“location”頭域顯示的地址就應該和客戶端發起請求的地址相對應,而不是代理服務器直接返回的地址信息,否則就會出現問題。該指令解決了這個問題,可以把代理服務器返回的地址信息更改為需要的地址信息,語法結構如下!

1 proxy_redirect  redirect  replacement;
2 proxy_redirect default;
3 proxy_redireect off;           #表示當前作用於下所有的proxy_redirect指令配置全部設置為無效。
#redirect,匹配“Location”頭域值的字符串,支持變量的使用和正則表達式
#replacement, 用於替換redirect變量內容的字符串,支持變量的引用。

通過兩個實例,來理解這個命令!【摘自nginx高性能web服務器詳解】

第一個例子

假設被代理服務器返回的響應頭中“location”頭域為

Location:  http://localhost/proxy/some/uri

該指令設置為:

proxy_pass http://localhost/proxy/  http://x.x.x.x/fromtend/;

nginx服務器會將“Location”頭域信息更改為:

Location:  http://x.x.x.x/fromtend/some/uri

這樣客戶端收到的響應信息頭部中的“Location”頭域已經被更改。註意還是為安全,把後端服務器的信息暴露出來是不安全的!

第二個例子

使用default,代理使用Location塊的uri變量作為replacement,並使用proxy_pass變量為redirect。下面的兩個配置結果是相等的。

#配置1
location  /server/
{
       proxy_pass  http://proxyserver/source/;
       proxy_redirect  default;   
}

#配置2
location  /server/
{
       proxy_pass  http://proxyserver/source/;
       proxy_redirect   http://proxyserver/source/  /server/;   
}

#配置1和配置2產生的結果是一樣的

15:proxy_intercept_errors指令

該指令用於配置一個狀態是開啟還是關閉。在開啟狀態時,如果後端服務器返回的http狀態碼為400或者大於400,則nginx服務器使用自己定義的錯誤頁(使用error_pages指令);如果關閉了該狀態,nginx服務器直接將後端服務器返回的http狀態返回給客戶端。

proxy_intercept_errors  on | off;

16:proxy_headers_hash_max_size指令

該指令用於配置存放http報文頭的哈希表的容量,語法結構為

proxy_headers_hash_max_size  size;

#size為http報頭哈希表容量上限,默認為512個字符。

nginx服務器為了能夠快速檢索http報文頭中的各項信息,比如服務器名稱,MIME類型,請求頭名稱,使用哈希表存儲這些信息。nginx服務器在申請存放http報文頭空間時,通常以固定大小為單位申請,該大小由此指令設定。

在nginx配置中,不僅能夠配置整個哈希表的上限,對於大部分內容,也可以配置其大小的上限。比如server_names_hash_max_size指令server_names_hash_bucket_size指令用來設置服務器名稱的字符數長度。

17:proxy_headers_hash_bucket_szie指令

該指令用於設置nginx服務器申請存放http報文的哈希表容量的單位大小,具體使用見上一個命令。

proxy_headers_hash_bucket_szie  size;
#size為設置容量,默認為64個字符

18:proxy_next_upstream指令

在配置nginx服務器反向代理時,如果使用了upstream指令配置了一組服務器作為被代理服務器,服務器組中各個服務器的訪問規則遵循upstream指令配置的輪詢規則,同時也可以使用該指令配置在發生哪些異常情況下,將請求順序交由下一個組內服務器處理。

proxy_next_upstream  status...;

status為設置的服務器返回的狀態,可以是一個或者多個。狀態取值如下:
  • error,在建立連接,向後端服務器發送請求,讀取響應頭時服務器發生連接錯誤。
  • timeout, 在建立連接,向後端服務器發送請求,讀取響應頭時服務器發生連接超時。
  • invalid_header, 後端服務器返回的響應頭為空或者無效。
  • http_500|http_502|http_503|http_504|http_404,後端服務器返回500,502,503,504,404狀態碼。
  • off,無法將請求發送到後端服務器。

19:proxy_ssl_session_reuse指令

該指令用於配置是否使用基於ssl安全協議的會話連接被代理的服務器。

proxy_ssl_session_reuse  on|off;

默認設置為開啟狀態。

我們通過實例來說明nginx反向代理的用法:

第一個實例,對所有的請求實現一般輪詢的負載均衡

    upstream backend 
    {
        server  10.0.102.214:8080;
        server  10.0.102.204:8080;
    }

    server {
        listen       80;
        server_name  localhost;
        root   html;
        index  index.html index.htm;

        location / {
            proxy_pass_header server;
            proxy_pass http://backend;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

#默認情況下,後端服務器組中每臺服務器的權重值為1,使用輪叫調度的策略。

第二個實例,對所有的請求實現加權輪叫調度

配置就是把上面後端服務器組中每臺服務器後面加上權重即可!

    upstream backend 
    {
        server  10.0.102.214:8080 weight=1;
        server  10.0.102.204:8080 weight=2;
    }

    server {
        listen       80;
        server_name  localhost;
        root   html;
        index  index.html index.htm;

        location / {
            proxy_pass_header server;
            proxy_pass http://backend;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

#權重高的服務器優先處理請求和響應,所有的請求都會在backend服務器組中實現加權負載均衡。

第三個實例,對不同資源實現負載均衡,這裏定義兩組後端服務器組,對圖片的訪問和對文件的訪問使用不同的服務器組,這樣就可以對不同資源做負載均衡!

#定義兩個服務器組,分別對文件和圖片進行處理 
upstream file_backend #定義文件服務器組 { server
10.0.102.220; server 10.0.102.221; } upstream image_backend #定義圖片服務器組 { server 10.0.102.214; server 10.0.102.204; } server { listen 80; server_name localhost; root html; index index.html index.htm; location /files/ { #針對文件訪問,使用下面的服務器組 proxy_pass_header server; proxy_pass http://file_backend/files/; } location /images/ { #針對圖片的訪問使用下面的服務器組,, proxy_pass http://image_backend/images/; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }

第四種情況,針對不同的域名做負載均衡。

在配置文件中可以配置多個server塊,每個塊都是一個虛擬主機,每個塊中根據server_name的不同,被轉發到後端不同的服務器上。

    upstream bbs_backend 
    {
        server  10.0.102.214;
        server  10.0.102.204;
    }

    upstream home_backend
    {
        server 10.0.102.214;
        server 10.0.102.204;
    }

    server {                                          #根據不同的域名,訪問到不同的服務器組
        listen       80;
        server_name  www.bbs.com;
        index  index.html index.htm;

        location   / {
            proxy_pass http://bbs_backend;
        }
  
    }

    server {
        listen       81;
        server_name  www.home.com;
        index  index.html index.htm;

        location   / {
            proxy_pass http://home_backend;
        }
    }

nginx反向代理-後端服務器組設置