Nginx4大模塊——proxy、headers、upstream、stream


  

一:ngx_http_proxy_module

       反向代理( reverse proxy) 方式是指用代理服務器來接受 Internet 上的連接請求, 然后將請求轉發給內部網絡中的上游服務器, 並將從上游服務器上得到的結果返回給 Internet 上請求連接的客戶端, 此時代理服務器對外的表現就是一個 Web 服務器。 充當反向代理服務器也是 Nginx 的一種常見用法( 反向代理服務器必須能夠處理大量並發請求), 下面將介紹Nginx作為 HTTP 反向代理服務器的基本用法。由於Nginx具有“強悍”的高並發高負載能力, 因此一般會作為前端的服務器直接向客戶端提供靜態文件服務。 但也有一些復雜、 多變的業務不適合放到 Nginx 服務器上, 這時會用Apache、 Tomcat 等服務器來處理。 於是, Nginx 通常會被配置為既是靜態Web服務器也是反向代理服務器( 如下圖所示), 不適合Nginx處理的請求就會直接轉發到上游服務器中處理。

Nginx proxy模塊相關指令

ngx_http_proxy_module模塊允許傳送請求到其它服務器,也就是做反向代理。下面提供一個基本的配置示例:

 

location / {
  root /usr/share/nginx/html;
  proxy_redirect default;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_connect_timeout 2;
  proxy_send_timeout 5;
  proxy_read_timeout 5;
  proxy_buffer_size 256k;
  proxy_buffers 4 256k;
  proxy_busy_buffers_size 256k;
  proxy_pass http://127.0.0.1:80;
}

 


ngx_http_proxy_module模塊常用指令解釋:

1)proxy_bind

Syntax: proxy_bind address [transparent] | off;
Default: —
Context: http, server, location
This directive appeared in version 0.8.22.

 



  在調用connect()前將上游socket綁定到一個本地地址,如果主機有多個網絡接口或別名,但是你希望代理的連接通過指定的接口或地址,可以使用這個指令。

  透明傳輸模式允許傳出連接到代理服務器起源於一個非本地IP地址,例如,從一個真實的IP地址的客戶端 ︰

proxy_bind $remote_addr transparent;

 


  為了使此參數工作,就必須以超級用戶的特權運行nginx的工作進程和配置內核路由表攔截來自代理服務器的網絡流量。

2)proxy_buffer_size

Syntax:    proxy_buffer_size size;
Default:proxy_buffer_size 4k|8k;
Context:http, server, location

 



  設置緩沖區的大小為size,nginx從被代理的服務器讀取響應時,使用該緩沖區保存響應的開始部分。這部分通常包含着一個小小的響應頭。該緩沖區大小默認等於proxy_buffers指令設置的一塊緩沖區的大小,但它也可以被設置得更小。

3)proxy_buffers

Syntax:    proxy_buffers number size;
Default:proxy_buffers 8 4k|8k;
Context:http, server, location

 


  設置用於讀取應答(來自被代理服務器)的緩沖區數目和大小,為每個連接設置緩沖區的數量是number參數,每塊緩沖區的大小是size參數。這些緩沖區用於保存從被代理的服務器讀取的響應。每塊緩沖區默認等於一個內存頁的大小。這個值默認是4K還是8K,取決於平台。

4)proxy_buffering

Syntax:    proxy_buffering on | off;
Default:proxy_buffering on;
Context:http, server, location

 



  代理的時候,開啟或關閉緩沖后端服務器的響應。

  當開啟緩沖時,nginx盡可能快地從被代理的服務器接收響應,再將它存入proxy_buffer_size和proxy_buffers指令設置的緩沖區中。

  如果響應無法整個納入內存,那么其中一部分將存入磁盤上的臨時文件。proxy_max_temp_file_size和proxy_temp_file_write_size指令可以控制臨時文件的寫入。

  當關閉緩沖時,收到響應后,nginx立即將其同步傳給客戶端。nginx不會嘗試從被代理的服務器讀取整個請求,而是將proxy_buffer_size指令設定的大小作為一次讀取的最大長度。

  響應頭“X-Accel-Buffering”傳遞“yes”或“no”可以動態地開啟或關閉代理的緩沖功能。 這個能力可以通過proxy_ignore_headers指令關閉。

5)proxy_busy_buffers_size

Syntax:    proxy_busy_buffers_size size;
Default:proxy_busy_buffers_size 8k|16k;
Context:http, server, location

 



  當開啟緩沖響應的功能以后,在沒有讀到全部響應的情況下,寫緩沖到達一定大小時,nginx一定會向客戶端發送響應,直到緩沖小於此值。

  這條指令用來設置此值。 同時,剩余的緩沖區可以用於接收響應,如果需要,一部分內容將緩沖到臨時文件。該大小默認是proxy_buffer_size和proxy_buffers指令設置單塊緩沖大小的兩倍。

6)proxy_max_temp_file

Syntax:    proxy_max_temp_file_size size;
Default:proxy_max_temp_file_size 1024m;
Context:http, server, location


  打開響應緩沖以后,如果整個響應不能存放在proxy_buffer_size和proxy_buffers指令設置的緩沖區內,部分響應可以存放在臨時文件中。 這條指令可以設置臨時文件的最大容量。

  而每次寫入臨時文件的數據量則由proxy_temp_file_write_size指令定義。

  將此值設置為0將禁止響應寫入臨時文件。

7)proxy_temp_file_write_size

 

Syntax:    proxy_temp_file_write_size size;
Default:proxy_temp_file_write_size 8k|16k;
Context:http, server, location

  在開啟緩沖后端服務器響應到臨時文件的功能后,設置nginx每次寫數據到臨時文件的size(大小)限制。 size的默認值是proxy_buffer_size指令和proxy_buffers指令定義的每塊緩沖區大小的兩倍, 而臨時文件最大容量由    proxy_max_temp_file_size指令設置。

8)proxy_temp_path

Syntax:    proxy_temp_path path [level1 [level2 [level3]]];
Default:proxy_temp_path proxy_temp;
Context:http, server, location

 


  定義從后端服務器接收的臨時文件的存放路徑,可以為臨時文件路徑定義至多三層子目錄的目錄樹。 比如,下面配置

proxy_temp_path /spool/nginx/proxy_temp 1 2;  


       那么臨時文件的路徑看起來會是這樣:

/spool/nginx/proxy_temp/7/45/00000123457

 


9)proxy_connect_timeout

Syntax:    proxy_connect_timeout time;
Default:proxy_connect_timeout 60s;
Context:http, server, location

 


設置與后端服務器建立連接的超時時間,應該注意這個超時一般不可能大於75秒。默認為60s,建議生產環境連接時間設置為1到2s。

10)proxy_http_version

Syntax:    proxy_http_version 1.0 | 1.1;
Default:proxy_http_version 1.0;
Context:http, server, location
This directive appeared in version 1.1.4.

 


  設置代理使用的HTTP協議版本,默認使用的版本是1.0,而1.1版本則推薦在使用keepalive連接時一起使用。我接觸的生產環境中都是設置http 1.1版本了。

11)proxy_ignore_client_abort

Syntax:    proxy_ignore_client_abort on | off;
Default:proxy_ignore_client_abort off;
Context:http, server, location

 


  決定當客戶端在響應傳輸完成前就關閉連接時,nginx是否應關閉后端連接。

12)proxy_pass

Syntax:    proxy_pass URL;
Default:—
Context:location, if in location, limit_except

 


  設置后端服務器的協議和地址,還可以設置可選的URI以定義本地路徑和后端服務器的映射關系。 這條指令可以設置的協議是“http”或者“https”,而地址既可以使用域名或者IP地址加端口(可選)的形式來定義:

proxy_pass http://localhost:8000/uri/;

 


  對於URI可選,一般情況下使用是不需要指定的,除非你需要的訪問方式就是這樣的。

  也可以使用UNIX域套接字路徑來定義,該路徑接在“unix”字符串后面,兩端由冒號所包圍,比如:

proxy_pass http://unix:/tmp/backend.socket:/uri/;

 


  如果proxy_pass沒有使用URI,傳送到后端服務器的請求URI一般客戶端發起的原始URI,如果nginx改變了請求URI,則傳送的URI是nginx改變以后的完整規范化URI:

location /path/ {
  proxy_pass http://127.0.0.1;
}

 


  如果proxy_pass使用了URI(/也算),當傳送請求到后端服務器時,規范化以后的請求路徑(原始請求URI)與location配置中的路徑的匹配部分將被替換為proxy_pass指令中定義的URI,其實這種實現方式就是做虛擬路徑代理,配置方式如下:

location /path/ {
  proxy_pass http://127.0.0.1/;
}

 



  虛擬路徑代理就是,比如說訪問”http://127.0.0.1/path/uri”地址,當匹配到這個location之后,通過”proxy_pass http://127.0.0.1/”代理到后端時,一個新的URL就成了”http://127.0.0.1/uri”這樣。

  其中的/path就稱為虛擬路徑,虛擬給用戶的,后端沒有真正的/path路徑,這里要特別注意”proxy_pass http://127.0.0.1/”最后的”/”,如果沒有這個”/”那么訪問就會出現404,因為你沒有給proxy_pass定義URI,所以不存在將規范化以后的請求路徑(原始請求URI)與location配置中的路徑的匹配部分將被替換為proxy_pass指令中定義的URI這一說法,切記。Nginx實現虛擬路徑代理

注意

  當使用一個正則表達式(~或~*)指定localtion時,在這種情況下,proxy_pass應該是一個沒有URI的指令,如果指定了URI,那么代理到后端時,URI會被去掉,從而變成了http://127.0.0.1/some/path,也就是說原始訪問URI不會做任何改變傳送到后端。

  還有一種情況,當URI使用rwrite重寫指令后,在這種情況下,proxy_pass應該是一個沒有URI的指令,如果指定了URI,那么代理到后端時,URI會被去掉,從而變成了http://127.0.0.1/some/path。

rewrite /name/([^/]+) /users?name=$1 break;

 


  最后,這種以代理的工作方式,一般都會使用到Nginx upstream,以此來做負載均衡。這種情況下直接給定一個upstream的名稱即可(需要先定義一個upstream),如下:

location / {
upstream test{
127.0.0.1:80;
}
proxy_pass http://test;
}

 


13)proxy_next_upstream

Syntax:    proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | 
http_403 | http_404 | non_idempotent | off ...;
Default:proxy_next_upstream error timeout;
Context:http, server, location

 


  當你使用Nginx proxy代理時,如果是代理到后端是使用upstream,那么這個指令就是指定在何種情況下,一個失敗的請求應該被發送到下一台后端服務器,有如下指令:

  error – 和后端服務器建立連接時,或者向后端服務器發送請求時,或者從后端服務器讀取響應時,出現錯誤;

  timeout – 和后端服務器建立連接時,或者向后端服務器發送請求時,或者從后端服務器讀取響應時,出現超時;

  invalid_header – 后端服務器返回空響應或者非法響應頭;

  http_500 – 后端服務器返回的響應狀態碼為500;

  http_502 – 后端服務器返回的響應狀態碼為502;

  http_503 – 后端服務器返回的響應狀態碼為503;

  http_504 – 后端服務器返回的響應狀態碼為504;

  http_404 – 后端服務器返回的響應狀態碼為404;

  off – 關閉proxy_next_upstream功能—出錯就選擇另一台上游服務器再次轉發。

  需要理解一點的是,只有在沒有向客戶端發送任何數據以前,將請求轉給下一台后端服務器才是可行的。也就是說,如果在傳輸響應到客戶端時出現錯誤或者超時,這類錯誤是不可能恢復的。

  另外Nginx1.7開始提供了將請求傳遞給下一台服務器可以通過重試的次數和時間進行限制。

14)proxy_next_upstream_timeout

Syntax:    proxy_next_upstream_timeout time;
Default:proxy_next_upstream_timeout 0;
Context:http, server, location
This directive appeared in version 1.7.5.

 


  限制了重試請求可以被傳遞給下一台服務器的時間,默認值為0將關閉這一限制。

15)proxy_next_upstream_tries

Syntax:    proxy_next_upstream_tries number;
Default:proxy_next_upstream_tries 0;
Context:http, server, location
This directive appeared in version 1.7.5.

 


  限制了重試請求可以被傳遞給下一台服務器的次數,默認值為0將關閉這一限制。

16)proxy_read_timeout

Syntax:    proxy_read_timeout time;
Default:proxy_read_timeout 60s;
Context:http, server, location

 


  定義從后端服務器讀取(接收)數據的超時時間(Nginx從客戶端接收到請求,然后把數據包轉發到后端服務器,后端服務器處理完請求后返回給Nginx服務器,Nginx接收后端數據包稱為一次read),此超時是指相鄰兩次讀操作之間的最長時間間隔,而不是整個響應傳輸完成的最長時間。如果后端服務器在超時時間段內沒有傳輸任何數據,連接將被關閉。默認時間為60s,建議值為2-4s。

17)proxy_send_timeout

Syntax:    proxy_send_timeout time;
Default:proxy_send_timeout 60s;
Context:http, server, location

 


  定義向后端服務器發送一次數據包的超時時間(Nginx從客戶端接收到請求,然后把數據包轉發到后端服務器稱為一次send),此超時是指相鄰兩次寫操作之間的最長時間間隔,而不是整個請求傳輸完成的最長時間。

  如果再向后端服務器發送數據包時,超過了超時時間的設置,那么連接將被關閉。默認時間為60s,建議值為2-4s。

18)proxy_set_header

Syntax:    proxy_set_header field value;
Default:proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context:http, server, location

 


  允許重新定義或者添加發往后端服務器的請求頭。value可以包含文本、變量或者它們的組合。 當且僅當當前配置級別中沒有定義proxy_set_header指令時,會從上面的級別繼承配置。 默認情況下,只有兩個請求頭會被重新定義:

proxy_set_header Host $proxy_host;
proxy_set_header Connection close;

 


  如果不想改變請求頭“Host”的值,可以這樣來設置:

proxy_set_header Host $http_host;

 


  但是,如果客戶端請求頭中沒有攜帶這個頭部,那么傳遞到后端服務器的請求也不含這個頭部。 這種情況下,更好的方式是使用$host變量——它的值在請求包含“Host”請求頭時為“Host”字段的值,在請求未攜帶“Host”請求頭時為虛擬主機的主域名:

proxy_set_header Host $host;

 


  此外,服務器名可以和后端服務器的端口一起傳送:

proxy_set_header Host $host:$proxy_port;

 


  如果某個請求頭的值為空,那么這個請求頭將不會傳送給后端服務器:

proxy_set_header Accept-Encoding "";


  $proxy_add_x_forwarded_for內置變量,將$remote_addr變量值添加在客戶端“X-Forwarded-For”請求頭的后面,並以逗號分隔。

   如果客戶端請求未攜帶“X-Forwarded-For”請求頭,$proxy_add_x_forwarded_for變量值將與$remote_addr變量相同。

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 

 

19)proxy_pass_header

Syntax:    proxy_pass_header field;
Default:—
Context:http, server, location

 


  允許指定跳過某些字段從代理服務器到客戶端,一般用在CDN中傳回來的字段信息,但不需要傳回到后端服務器,就可以使用proxy_pass_header指令跳過。

20)proxy_redirect

Syntax:    proxy_redirect default;
proxy_redirect off;
proxy_redirect redirect replacement;
Default:proxy_redirect default;
Context:http, server, location

 


  設置后端服務器“Location”響應頭和“Refresh”響應頭的替換文本。 假設后端服務器返回的響應頭是 “Location: http://localhost:8000/two/some/uri/”,那么指令

proxy_redirect http://localhost:8000/two/ http://frontend/one/;

 


  將把字符串改寫為 “Location: http://frontend/one/some/uri/”。

  replacement字符串可以省略服務器名:

proxy_redirect http://localhost:8000/two/ /;

 


  此時將使用代理服務器的主域名和端口號來替換。如果端口是80,可以不加。

  用default參數指定的默認替換使用了location和proxy_pass指令的參數。因此,下面兩例配置等價:

location /one/ {
proxy_pass http://upstream:port/two/;
proxy_redirect default;
}

 

location /one/ {
  proxy_pass http://upstream:port/two/;
  proxy_redirect http://upstream:port/two/ /one/;
}

 


而且因為同樣的原因,proxy_pass指令使用變量時,不允許本指令使用default參數。

replacement字符串可以包含變量:

proxy_redirect http://localhost:8000/ http://$host:$server_port/;

 


而redirect字符串從1.1.11版本開始也可以包含變量:

proxy_redirect http://$proxy_host:8000/ /;

 


同時,從1.1.11版本開始,指令支持正則表達式。使用正則表達式的話,如果是大小寫敏感的匹配,redirect以“~”作為開始,如果是大小寫不敏感的匹配,redirect以“~*”作為開始。而且redirect的正則表達式中可以包含命名匹配組和位置匹配組,而在replacement中可以引用這些匹配組的值:

proxy_redirect ~^(http://[^:]+):\d+(/.+)$ $1$2;
proxy_redirect ~*/user/([^/]+)/(.+)$ http://$1.example.com/$2;

 


除此以外,可以同時定義多個proxy_redirect指令:

proxy_redirect default;
proxy_redirect http://localhost:8000/ /;
proxy_redirect http://www.example.com/ /;

 


另外,off參數可以使所有相同配置級別的proxy_redirect指令無效:

proxy_redirect off;
proxy_redirect default;
proxy_redirect http://localhost:8000/ /;
proxy_redirect http://www.example.com/ /;

 

二:ngx_http_upstream_module

實例

upstream appservers {  
    zone appservers 64k;  
    #默認權重為1
    server appserv1.example.com      weight=5;  
    server appserv2.example.com:8080 fail_timeout=5s slow_start=30s;  
    server 192.0.2.1                 max_fails=3;  
  
    server reserve1.example.com:8080 backup;  
    server reserve2.example.com:8080 backup;  
}  
  
server {  
    location / {  
        proxy_pass http://appservers;  
        health_check;  
    }  
  
    location /upstream_conf {  
        upstream_conf;  
        allow 127.0.0.1;  
        deny all;  
    }  
} 

 

  1.weight=number

  設定服務器的權重,默認是1。

  2.max_fails=number

  設定Nginx與服務器通信的嘗試失敗的次數。

  3.fail_timeout=time

  設定

  • 統計失敗嘗試次數的時間段。在這段時間中,服務器失敗次數達到指定的嘗試次數,服務器就被認為不可用。
  • 服務器被認為不可用的時間段。

  默認情況下,該超時時間是10秒。backup標記為備用服務器。當主服務器不可用以后,請求會被傳給這些服務器。

  4.down

  標記服務器永久不可用,可以跟ip_hash指令一起使用。

  5.route=string

  設置服務器路由名稱。

1.ip_hash

  該指令通過IP地址的哈希值確保客戶端均勻的連接所有服務器,鍵值基於c類地址

  如果需要暫時刪除其中一台服務器,則應該使用該down參數進行標記,以便保留客戶端IP地址的當前散列。

 

2.keepalive connections

  該connections參數設置保留在每個輔助進程緩存中的上游服務器的空閑保持連接的最大數量。當這個數字被超過時,最近最少使用的連接被關閉。

  對於HTTP代理,proxy_http_version指令應該設置為“1.1”,同時“Connection”頭的值也應被清空。

  

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

 

3.least_conn

   指定服務器組的負載均衡方法,根據其權重值,將請求發送到活躍連接數最少的那台服務器。 如果這樣的服務器有多台,那就采取有權重的輪轉法進行嘗試。

 


免責聲明!

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



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