文字:
proxy子產品
HTTP反向代理處理流程
proxy子產品
功能:對上遊伺服器使用http/https協定進行反向代理。
文法:proxy_pass URL;
上下文:if,if in location
URL規則
必須以http或者https開頭,接下來是域名|IP位址|Unix socket|upstream的名字。
域名和IP位址後邊可以加端口。
最後可以帶上可選的URI
URL參數中帶有URI會導緻法向上遊的URL不同
不攜帶URI,則将用戶端請求中的URL直接發送給上遊伺服器。
攜帶URI,則對使用者請求中的URL做如下操作:
将location中比對上的一段替換為該URI。
小例子:
upstreamproxyups {
server127.0.0.1:8012 weight=1;
keepalive2;
}
server{
set_real_ip_from 192.168.188.60;
real_ip_headerX-Forwarded-For;
listen8080;
location/a {
proxy_http_version1.1;
proxy_set_headerConnection"";
}
上例中,我配置上遊伺服器,傳回$uri的内容。
上邊proxy_pass的配置下:curl 192.168.188.60:8080/a/c,會輸出 uri:/a/c,會原封不動地把URI發送給上遊伺服器。
如果上邊第一個proxy_pass的注釋打開,注釋掉第二條。curl 192.168.188.60:8080/a/c,會輸出:uri:/www/c,在location中先進行URI替換,然後再發送給上遊伺服器。
根據指令修改發往上遊的請求
生成發往上遊的請求行
proxy_method指令
文法:proxy_method method;
上下文:http,server,location。
作用:設定傳給上遊伺服器的http請求的方法。
proxy_http_version
文法proxy_http_version 1.0|1.1
預設:proxy_http_version 1.0;
如果使用keepalive功能的時候,就必須使用proxy_http_version 1.1。
proxy_pass_requests_headers
作用:是否把使用者請求的頭部發給上遊。如果設定為off,那麼就不再把使用者請求的header發給上遊伺服器了。
預設:proxy_pass_requests_headers on;
proxy_pass_requests_body
作用:是否把使用者請求的包體發給上遊。
預設:proxy_pass_requests_body on;
proxy_set_header
預設:proxy_set_header Host $proxy_host; proxy_set_header Connection close;
作用:在上邊proxy_pass_requests_headers為on的情況下,我可以自己設定傳給上遊伺服器的header的頭部内容。
proxy_set_body
作用:作用:在上邊proxy_pass_requests_body為on的情況下,我可以自己設定傳給上遊伺服器的body的内容。
小例子:
反向代理配置
upstreamproxyups {
server127.0.0.1:8012 weight=1;
}
server{
listen8080;
location/a {
proxy_methodPOST;
# proxy_pass_request_headers off;
# proxy_pass_request_body off;
proxy_set_headerHost'yang';
proxy_set_body'helow world';
proxy_http_version1.1;
proxy_set_headerConnection"";
}
}
上遊伺服器配置
server{
listen8012;
return200'8012 server response
uri:$uri
method:$request_method
request:$request
Host:$Host
http_name:$http_name\n';
}
執行測試指令:curl -H 'name:yudalihua' 192.168.188.60:8080/a/b
我在反向代理中設定的header能夠直接顯示出來,但是設定的body内容需要抓包才能看到,使用如下指令在8012端口抓包:tcpdump -i lo port 8012 -A -s 0 ,就能夠看到在反向代理子產品設定的body内容“hello world”
接收使用者請求包體的方式
proxy_request_bufferring
預設:proxy_request_bufferring on;
當設定為on的情況
用戶端網速比較慢
上遊服務并發處理能力低
适應高吞吐量的場景。
當設定為off的情況
更及時的響應
降低nginx讀寫磁盤的消耗。
一旦開始發送内容,proxy_next_upstream指令失效。
client_body_buffer_size
預設:client_body_buffer_size 8k|18k
原理:
在接收header的時候,可能會接收到部分body。
判斷接收到的body是否已經是所有的body。
如果已經接收完了body,則不配置設定client_body_buffer
若剩餘待接收包體長度小于client_body_buffer_size,則僅配置設定所需要的。
否則,我們就配置設定client_body_buffer_size 大小的記憶體,用于接收用戶端的body。不管使用者的body是1G還是多大,我們都是通過這麼大小的緩存,一段一段地收。
client_body_in_single_buffer
client_max_body_size
預設:client_max_body_size 1m;
用戶端body的最大長度,預設是1M,非常小,不夠用。
作用:針對請求頭部中含有Content-length時,如果其字段超過了client_max_body_size,就傳回413錯誤。
client_body_temp_path
預設:client_body_temp_path client_body_temp;
client_body_in_file_only
文法:client_body_in_file_only on|clean| off;
預設:client_body_in_file_only off;
如果設定為on:
那麼用戶端的請求的body會被一直儲存在檔案中,友善我們定位問題。
如果設定為off:
那麼用戶端處理完body之後,可能該檔案就被删除了。
client_body_timeout:
文法:client_body_timeout time;
預設:client_body_timeout 60s;
作用:兩次讀取body之間的最大時延,如果讀取包體超過了最大時延,傳回408錯誤。
與上遊服務建立連接配接
proxy_connect_timeout
預設:proxy_connect_timeout 60s;
和上遊建立TCP連接配接的逾時時間。
如果逾時了,上遊肯定是沒有響應的,那麼nginx會生成一個502的響應碼。
proxy_next_upstream http_502
作用:如果逾時,或者其他原因,和一個上遊伺服器建立TCP連接配接出現錯誤,那麼就選擇另一個upstream進行嘗試。
proxy_socket_keepalive
預設:proxy_socket_keepalive off;
作用:反向代理和上遊服務是否開啟TCP的keepalive功能。
上下文:http,server,location。
TCP的keepalive
判斷TCP連接配接的對方是否存在,如果不存在,就及時關閉,減少資源的浪費。
keepalive
文法:keepalive connections
上下文:upstream
keepalive_requests
文法:keepalive_requests number;
預設:keepalive_requests 100;
上下文:upstream
proxy_bind
文法:proxy_bind address [transparent] |off;
address
address可以使用變量,例如$remote_addr
address可以使用非本機位址,但是必須加上transparent關鍵字。
作用:就是修改請求封包的IP頭部中的source IP Address為我們指定的IP位址。
proxy_ignore_client_abort
預設:proxy_ignore_client_abort off;
如果設定為on:
當用戶端到反向代理的連接配接斷開的時候,忽略這種情況,不斷開反向代理同上遊伺服器的連接配接。
會給上遊帶來很大的性能壓力。
如果設定為 off:
當用戶端和nginx斷開連接配接的時候,nginx和上遊伺服器也斷開連接配接。
預設為off。
proxy_send_timeout
預設:proxy_send_timeout 60s;
把請求發送給上遊伺服器,後請求的逾時時間。
接收上遊的響應
proxy_buffer_size
預設:proxy_buffer_size 4k|8k;
作用
限制了反向代理可以接收的上遊的最大header,如果上遊傳回的響應有cookie等非常大的資料,可能會導緻整個header超出了nginx處理的能力。
會報錯,在錯誤日志檔案中生成:upstream sent too big header
proxy_buffering
預設:proxy_buffering on;
如果設定為ON
那麼nginx接收上遊的服務發送來的響應body,會先緩存起來,然後再發送出去。
預設設定為ON,因為nginx和上遊伺服器都是在内網中,網速非常快。而nginx和用戶端直接網速要慢很多,如果發送一個很大的body的話,那麼會導緻nginx和上遊伺服器有長時間的連接配接。而上遊服務,比如Django,或者Tomcat的并發能力是非常弱的。
表明我們想要快速釋放nginx和上遊伺服器之間的連接配接。
proxy_buffers
文法:proxy_buffers number size;
預設:proxy_buffers 8 4k|8k;
作用:
上個指令緩存上遊的響應body的時候,要寫到磁盤,就需要進行IO。
試想,如果我們不把上遊的body放到磁盤中,而是放到緩存中可以嗎?
這就是這個指令的效果,預設配置設定8個4k大小的緩存,也就是32k,如果這個緩存能夠放下上遊的body,就放到緩存中;否則,還是會向磁盤中寫。
proxy_max_temp_file_size
預設:proxy_max_temp_file_size 1024m;
作用:
當把上遊響應body寫到磁盤的時候,限制這個磁盤檔案大小的最大值。
如果超出了門檻值,也會出錯。
proxy_temp_write_sze
預設:proxy_temp_write_sze 8k|16k;
作用:當把上遊的body寫入磁盤的時候,每一次寫磁盤,寫進去的機關,一次8k或者16k。
proxy_temp_path
預設:proxy_temp_path proxy_temp;
作用:把上遊的body寫入磁盤時候,檔案的路徑。
proxy_busy_buffers_size
預設:proxy_busy_buffers_size 8k|16k;
作用:
及時轉發body。
當從上遊接收一個很大的response body的時候,會先把它寫到磁盤或者緩存,但是每寫好8k或者16k,就像用戶端發送一次。
proxy_read_timeout
預設:proxy_read_timeout 60s;
作用:TCP層的概念,兩次讀取之間的逾時時間是60秒,如果超過了這個事件,TCP連接配接應該就會斷開了。
proxy_limit_rate
預設:proxy_limit_rate 0;
作用
限制讀取上遊響應的速度。
設定為0,表示不限制。
proxy_store
如果設定為on
nginx接收上遊的響應body生成的臨時檔案,我們可以做持久化處理。
預設開啟。
proxy_store access
設定上邊持久化檔案的通路權限。
小例子:
nginx配置
server{
listen8080;
root/tmp;
location/a {
proxy_storeon;
proxy_store_accessuser:rw group:rw all:r;
}}
上遊服務配置
server{
listen8012;
location/ {
roothtml;
}
}
curl 192.168.188.60:8080/a.txt 這個指令上遊服務給我把a.txt檔案發送過來了,按道理說我也設定了持久化了,但是不知道為什麼,就是在nginx的機器上看不到把temp檔案持久化的結果。
處理上遊的響應
proxy_ignore_headers field ...;
功能:上遊伺服器的某些響應頭可能會改變nginx的行為。這個指令可以讓指定的響應頭失效。
可以禁用功能的頭部:
proxy_hide_header field;
功能:對于上遊響應中的某些頭部,設定預設不對用戶端轉發。
proxy_cookie_domain
proxy_cookie_path
上邊兩個指令都是nginx修改從上遊伺服器傳回的Set-Cookie頭部
proxy_redirect
nginx修改從上遊伺服器傳回的響應中的location頭部。
上遊出現失敗時的容錯方案
proxy_next_upstream
前提:上遊沒有向用戶端發送任何内容,哪怕一個位元組。
配置:
error
與上遊建立連接配接、讀取響應、發送請求,等等,任何一個環境出現了錯誤,都可以滿足條件,激活這個 指令。
timeout
命中 connetc_timeout 、 read_timeout等情景,會激活這個指令,重新選取一個upstream
invalid_header
收到的上遊的HTTP的header是不合法的。
http_
可以跟一個明确的響應code。
可以根據這樣的一個code去選擇另一個upstream
off
不開啟這個指令。
proxy_next_upstream_timeout
開始選用另一個upstream,直到選中某個upstream的逾時時間。
proxy_next_upstream_tries
如果設定為0,表示不再限制。
小例子一:
nginx的配置
upstreamnextups {
server127.0.0.1:8012 weight=1;
server127.0.0.1:8011 weight=1;
}
server{
listen8080;
location/ {
proxy_connect_timeout1s;
proxy_next_upstream off;
}
上遊伺服器的配置
server{
listen8011;
return200'8011 server response\n';
}
server{
listen8014;
return200'8012 server response\n';
}
上邊nginx中的upstream配置了兩個服務,分别在8011和8012端口;我上遊伺服器沒有開8012端口。
proxy_next_upstream 的值:
如果是off,執行curl 192.168.188.60:8080,可能會出錯,因為請求還是會被分發到8012端口上,nginx可能等一定時間,就會向不存在的端口上發送請求,就會傳回錯誤。
如果是error,當執行curl 192.168.188.60:8080時,不會傳回錯誤,請求都被分發到了8012端口上了。
小例子二、
nginx的配置
server{
listen8080;
location/httperr {
proxy_next_upstream http_500;
}
上遊服務的配置
server{
listen8011;
return200'8011 server response\n';
}
server{
listen8012;
return500'8012 system error\n';
}
執行curl 192.168.188.60:8080/httperr 指令,傳回根據proxy_next_upstream的值
如果為http_500
那麼所有的curl結果,都是8011 server response
如果為off,或者注釋掉這一行
那麼curl結果就是8011 server response 或者 8012 system error
proxy_intercept_errorson|off
預設為off。
作用:當上遊響應的響應碼>=300時,應該把響應傳回用戶端還是按照error_page指令處理。
總之來說,就是用error_page來攔截上遊失敗指令。
小例子:
nginx配置。
server{
listen8080;
error_page 500/a.txt;
location/intercept {
proxy_intercept_errorson;
}
}
上遊伺服器配置
server{
listen8012;
return500'8012 system error\n';
}
上邊設定了proxy_intercept_errors為on,那麼curl 192.168.188.60:8080/intercep,上遊伺服器會傳回500,這個500,被error_page攔截,進而執行了error_page的指令。
注意:error_page隻能攔截傳回值和他後邊code一樣的響應。