簡介
nginx是開發中常用的web server,又可以做反向代理,另外k8s中的ingress默認使用的也是nginx,所以有必要深入了解下nginx的相關知識,及一些必要的原理知識。
常用指令
location
location [=|~|~*|^~|@] pattern { ... }
- =代表路徑完全匹配
- ~區分大小寫的正則匹配
server {
server_name web.com;
location ~ ^/abcd$ {
[…]
}
}
^/abcd\(這個正則表達式表示字符串必須以/開始,以\)結束,中間必須是abcd
http://web.com/abcd匹配(完全匹配)
http://web.com/ABCD不匹配,大小寫敏感
http://web.com/abcd?param1¶m2匹配
http://web.com/abcd/不匹配,不能匹配正則表達式
http://web.com/abcde不匹配,不能匹配正則表達式
- ~* 不區分大小寫的正則匹配
- ^~ 普通字符匹配,不是正則匹配。如果該選項匹配,只匹配該選項,不匹配別的選項,一般用來匹配目錄
- @ 定義一個命名的location,使用在內部定向時,例如error_page,try_files
查找的順序及優先級
當有多條 location 規則時,nginx 有一套比較復雜的規則,優先級如下:
1). =前綴的指令嚴格匹配這個查詢。如果找到,停止搜索。
2). 所有剩下的常規字符串,最長的匹配。如果這個匹配使用^~前綴,搜索停止。
3). 正則表達式,在配置文件中定義的順序。
4). 如果第3條規則產生匹配的話,結果被使用。否則,如同從第2條規則被使用。
順序or優先級: (location =) > (location ^~ 路徑 最長匹配的意思) > (location ,* 正則順序) > (location 部分起始路徑) > (/)
rewrite模塊
break
break
Context: server, location, if
停止執行 ngx_http_rewrite_module 的指令集,但是其他模塊指令是不受影響的
官方:
last
stops processing the current set of ngx_http_rewrite_module directives followed by a search for a new location matching the changed URI;
break
stops processing the current set of ngx_http_rewrite_module directives;
last: 停止當前這個請求,並根據rewrite匹配的規則重新發起一個請求。新請求又從第一階段開始執行…
break:相對last,break並不會重新發起一個請求,只是跳過當前的rewrite階段,並執行本請求后續的執行階段…
實例
server {
listen 80 default_server;
server_name dcshi.com;
root www;
location /break/ {
rewrite ^/break/(.*) /test/$1 break;
echo "break page";
}
location /last/ {
rewrite ^/last/(.*) /test/$1 last;
echo "last page";
}
location /test/ {
echo "test page";
}
}
if
Context: server, location
依據指定的條件決定是否執行 if 塊語句中的內容
if 中的幾種 判斷條件
- 一個變量名,如果變量 $variable 的值為空字符串或者字符串"0",則為false
- 變量與一個字符串的比較 相等為(=) 不相等為(!=) 注意此處不要把相等當做賦值語句啊
- 變量與一個正則表達式的模式匹配 操作符可以是(~ 區分大小寫的正則匹配, ~不區分大小寫的正則匹配, !~ !~,前面兩者的非)
- 檢測文件是否存在 使用 -f(存在) 和 !-f(不存在)
- 檢測路徑是否存在 使用 -d(存在) 和 !-d(不存在) 后面判斷可以是字符串也可是變量
- 檢測文件、路徑、或者鏈接文件是否存在 使用 -e(存在) 和 !-e(不存在) 后面判斷可以是字符串也可是變量
- 檢測文件是否為可執行文件 使用 -x(可執行) 和 !-x(不可執行) 后面判斷可以是字符串也可是變量
set $variable "0";
if ($variable) {
# 不會執行,因為 "0" 為 false
break;
}
# 使用變量與正則表達式匹配 沒有問題
if ( $http_host ~ "^star\.igrow\.cn$" ) {
break;
}
# 字符串與正則表達式匹配 報錯
if ( "star" ~ "^star\.igrow\.cn$" ) {
break;
}
# 檢查文件類的 字符串與變量均可
if ( !-f "/data.log" ) {
break;
}
if ( !-f $filename ) {
break;
}
if中&&的實現,參考:
// 匹配click路徑且參數中帶有name=walkingsun 重定向到click-ios路徑
set $flag 0;
if ( $uri = /click) {
set $flag 1;
}
if ( $args ~ name=walkingsun ) {
set $flag 1$flag;
}
if ( $flag = 11 ) {
rewrite ^/(.*) $uri-ios break;
}
return
Context: server, location, if
return code [text];
return code URL;
return URL;
停止處理並將指定的code碼返回給客戶端。 非標准code碼 444 關閉連接而不發送響應報頭
有一種特殊情況,就是重定向的url可以指定為此服務器本地的urI,這樣的話,nginx會依據請求的協議$scheme, server_name_in_redirect 和 port_in_redirect自動生成完整的 url (此處要說明的是server_name_in_redirect 和port_in_redirect 指令是表示是否將server塊中的 server_name 和 listen 的端口 作為redirect用 )
變量
定義變量
set $foo hello;
內置變量
- $request_method 請求方式
- $args query params
- $request_uri $request_uri 則用來獲取請求最原始的 URI (未經解碼,並且包含請求參數)
- $uri 獲取當前請求的 URI(經過解碼,並且不含請求參數)
- $arg_xxx 特別常用的內建變量其實並不是單獨一個變量,而是有無限多變種的一群變量,即名字以 arg_ 開頭的所有變量,我們估且稱之為 $arg_XXX 變量群。一個例子是 $arg_name,這個變量的值是當前請求中名為 name 的參數的值,而且還是未解碼的原始形式的值。
location /test-arg {
echo "name: $arg_name";
echo "class: $arg_class";
}
$arg_name 不僅可以匹配 name 參數,也可以匹配 NAME 參數,抑或是 Name,Nginx 會在匹配參數名之前,自動把原始請求中的參數名調整為全部小寫的形式
- $cookie_XXX 取 cookie 值變量群
- $http_XXX
全局變量
arg_PARAMETER #這個變量包含GET請求中,如果有變量PARAMETER時的值。
args #這個變量等於請求行中(GET請求)的參數,如:foo=123&bar=blahblah;
binary_remote_addr #二進制的客戶地址。
body_bytes_sent #響應時送出的body字節數數量。即使連接中斷,這個數據也是精確的。
content_length #請求頭中的Content-length字段。
content_type #請求頭中的Content-Type字段。
cookie_COOKIE #cookie COOKIE變量的值
document_root #當前請求在root指令中指定的值。
document_uri #與uri相同。
host #請求主機頭字段,否則為服務器名稱。
hostname #Set to themachine’s hostname as returned by gethostname
http_HEADER
is_args #如果有args參數,這個變量等於”?”,否則等於”",空值。
# nginx取請求中header的XXX的值
http_user_agent #客戶端agent信息
http_cookie #客戶端cookie信息
http_origin #origin,而一般跨域請求都會將請求的來源放在origin中(瀏覽器會往跨域請求的header上面加origin這個header)
limit_rate #這個變量可以限制連接速率。
query_string #與args相同。
request_body_file #客戶端請求主體信息的臨時文件名。
request_method #客戶端請求的動作,通常為GET或POST。
remote_addr #客戶端的IP地址。
remote_port #客戶端的端口。
remote_user #已經經過Auth Basic Module驗證的用戶名。
request_completion #如果請求結束,設置為OK. 當請求未結束或如果該請求不是請求鏈串的最后一個時,為空(Empty)。
request_method #GET或POST
request_filename #當前請求的文件路徑,由root或alias指令與URI請求生成。
request_uri #包含請求參數的原始URI,不包含主機名,如:”/foo/bar.php?arg=baz”。不能修改。
scheme #HTTP方法(如http,https)。
server_protocol #請求使用的協議,通常是HTTP/1.0或HTTP/1.1。
server_addr #服務器地址,在完成一次系統調用后可以確定這個值。
server_name #服務器名稱。
server_port #請求到達服務器的端口號
Module
ngx_http_mirror_module
implements mirroring of an original request by creating background mirror subrequests. Responses to mirror subrequests are ignored.
通過創建后台鏡像子請求實現原始請求的鏡像。對鏡像子請求的響應將被忽略;
場景:可以做流量復制,不關心響應。作為機房遷移上雲的過渡挺合適的,或者說是作為復制請求測試。
location / {
mirror /mirror;
proxy_pass http://backend;
}
location = /mirror {
internal;
proxy_pass http://test_backend$request_uri;
}
參考:http://nginx.org/en/docs/http/ngx_http_mirror_module.html