nginx服務器的反向代理時其最經常使用的重要功能之一,在實際工做中應用普遍,涉及的配置指令也比較多。下面會盡可能詳細地介紹對應的指令,及其使用狀態。html
反向代理通常是互聯網須要向內網拉取資源,好比訪問一個web網站時,互聯網應用經過一個代理服務器到後面真實的web服務器拉取應用所需的數據。前端
nginx服務器反向代理用到的指令若是沒有特別的說明,原則上能夠出如今nginx配置文件的http塊,server塊和location塊中,可是同正向代理同樣,通常是搭建在nginx服務器中單獨配置一個server塊用來設置代理服務。這些指令主要由ngx_http_proxy_module模塊進行解析和處理。該模塊是nginx服務器的標準http模塊。nginx
nginx服務器支持設置一組服務器做爲後端服務器,所以在說明nginx反向代理指令以前,首先說明nginx的後端服務器組的配置。web
後端服務器組的指令,是由nginx標準模塊ngx_http_upstream_module進行解析和處理的。正則表達式
1.upstream指令,該指令是設置後端服務器組的主要指令,其餘指令都在該指令中進行配置。語法結構爲算法
upstream name {
...... #後端服務器設置
}
#其中name是後端服務器的組名。花括號中列出了後端服務器組中包含的服務器。
默認狀況下,某個服務器組接收到請求後,按照輪叫調度策略順序選擇組內的服務器處理請求。若是一個服務器在處理請求過程當中出現錯誤,則請求會被順序交給組內的下一個服務器處理,一直到返回正常響應。可是若是全部組內的服務器出錯,則返回最後一個服務器的處理結果。還能夠在根據每一個服務器的處理能力不一樣,給各個服務器配置不一樣的權重。權重的配置包含在server指令中。後端
2:server指令安全
該指令用於設置組內的服務器,語法結構爲服務器
server address [parameters];
#address: 服務器的地址,能夠是包含端口號的ip地址,域名或者以「unix:」爲前綴的用於進程間通訊的套接字
#parameters: 爲當前服務器的更多屬性,以下。
若設置爲0則不用上面的辦法檢查服務器是否有效、網絡
該變量設置的時間爲認爲服務器無效持續的時間。在這個時間內再也不檢查該服務器的狀態,並一直認爲它是無效的。默認是10s。
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 從新定義代理請求Host
和Connection
中的兩個頭字段,並刪除了值爲空字符串的頭字段。其中請求頭Host
被設置爲了變量$proxy_host
,Connection
被設定爲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爲設置的服務器返回的狀態,能夠是一個或者多個。狀態取值以下:
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; } }