Nginx 的變量到底是怎麼一回事?

以前說了不少關於 Nginx 模塊的內容,還有一部分很是重要的內容,那就是 Nginx 的變量。變量在 Nginx 中能夠說無處不在,認識瞭解這些變量的做用和原理一樣是必要的,下面幾乎囊括了關於 Nginx 的全部變量,單獨看起來可能比較枯燥,放心,後面依然有實戰內容。nginx

Nginx 變量的運行原理

圍繞 Nginx 中的變量模塊能夠分爲兩類,一類是提供變量的模塊,另一類是使用變量的模塊。git

  • 提供變量的模塊
    • 在 Preconfiguration 源代碼中定義變量名以及能夠解析出變量的方法
  • 使用變量的模塊
    • 解析 nginx.conf 時定義變量的使用方式

也就是在 Nginx 啓動時,已經定義了變量,而只有當真正處理請求的時候,纔會根據 nginx.conf 解析出來的變量使用方式調用 Preconfiguration 中定義的方法來實際獲取值。github

這也是變量的兩個特性:服務器

  • 惰性求值:只有使用的時候纔會去調方法解析
  • 變量值能夠時刻變化,其值爲使用的那一時刻的值。例如發送響應包體字節數,實際在發送的過程當中是一直在變化的。

除了 Nginx 的模塊以外,Nginx 框架也包含許多的變量,這些變量不須要經過編譯模塊來引入,並且,Nginx 框架所提供的變量每每反映了處理請求的細節,所以,瞭解 Nginx 框架所提供的變量是十分有必要的。cookie

HTTP 請求相關的變量

先來看一下關於 HTTP 請求的相關變量。框架

  • arg_參數名:URL 中某個具體參數的值curl

  • query_string:與 args 變量徹底相同tcp

  • args:所有 URL 參數學習

  • is_args:若是請求 URL 中有參數則返回 ?,不然返回空url

  • content_length:HTTP 請求中標識包體長度的 Content-Length 頭部的值。若是請求中沒有攜帶這個參數,那麼就取不到對應的值。

  • content_type:標識請求包體類型的 Content-Type 頭部的值。一樣須要用戶請求中攜帶對應的參數。

  • uri:請求的 URI(不一樣於 URL,不包括 ? 後的參數)

  • document_uri:與 uri 徹底相同。因爲歷史緣由而存在的。

  • request_uri:請求的 URL(包括 URI 以及完整的參數)

  • scheme:協議名,例如 HTTP 或者 HTTPS

  • request_method:請求方法,例如 GET 或者 POST

  • request_length:全部請求內容的大小,包括請求行、頭部、包體等

  • remote_user:由 HTTP Basic Authentication 協議傳入的用戶名

  • request_body_file:不少時候會將用戶請求的包體存放到文件中,這個變量就是臨時存放請求包體的文件

    • 若是包體很是小則不會存文件
    • client_body_in_file_only 指令強制全部包體存入文件,且可決定是否刪除
  • request_body:請求中的包體,這個變量當且僅當使用反向代理,且設定用內存暫存包體時纔有效

  • request:原始的 URL 請求,含有方法與協議版本,例如 GET /?a=1&b=22 HTTP/1.1

  • host

    • 先從請求行中獲取
    • 若是含有 Host 頭部,則用其值替換掉請求行中的主機名
    • 若是前二者都取不到,則使用匹配上的 server_name
  • http_頭部名字:返回一個具體請求頭部的值

    特殊變量,這些變量會作一些處理。

    • http_host
    • http_user_agent
    • http_referer
    • http_via
    • http_x_forwarded_for
    • http_cookie

    通用變量,除了以上的變量,均可以取到對應的值。

TCP 鏈接相關的變量

下面是關於 TCP 鏈接的變量。

  • binary_remote_addr:客戶端地址的整形格式,對於 IPv4 是 4 字節,對於 IPv6 是 16 字節,因此在 limit_req 和 limit_conn 中一般能夠用做 key (詳見:Nginx 處理 HTTP 請求的 11 個階段 中的 preaccess 階段)
  • connection:遞增的鏈接序號
  • connection_requests:當前鏈接上執行過的請求數,對 keepalive 鏈接有意義
  • remote_addr:客戶端地址
  • remote_port:客戶端端口
  • proxy_protocol_addr:若使用了 proxy_protocol 協議,則返回協議中的地址,不然返回空
  • proxy_protocol_port:若使用了 proxy_protocol 協議則返回協議中的端口,不然返回空
  • server_addr:服務端地址
  • server_port:服務器端端口
  • TCP_INFO:TCP 內核層參數,包括 $tcpinfo_rtt, ​$tcpinfo_rttvar,​$tcpinfo_snd_cwnd, $tcpinfo_rcv_space
  • server_protocol:服務器端協議,例如 HTTP/1.1

Nginx 處理請求過程當中產生的變量

Nginx 處理 HTTP 請求的過程當中也會產生不少變量。

  • request_time:請求處理到如今的耗時,單位爲秒,精確到毫秒
  • server_name:匹配上請求的 server_name 值
  • https:若是開啓了 TLS/SSL 則返回 on,不然返回空
  • request_completion:若請求處理完則返回 OK,不然返回空
  • request_id:以 16 進制輸出的請求表示 id,該 id 共含有 16 個字節,是隨機生成的
  • request_filename:待訪問文件的完整路徑
  • document_root:由 URI 和 root、alias 規則生成的文件夾路徑
  • realpath_root:將 document_root 中的軟連接等換成真實路徑
  • limit_rate:返回客戶端響應時的速度上限,單位爲每秒字節數。能夠經過 set 指令修改對請求產生的效果

發送 HTTP 響應時相關的變量

  • body_bytes_sent:響應中 body 包體的長度

  • bytes_sent:所有 http 響應的長度

  • status:http 響應中的返回碼

  • sent_trailer_名字:把響應結尾內容裏的值返回

  • sent_http_頭部名字:響應中某個具體頭部的值

    特殊處理,下面這些變量須要通過特殊處理:

    • sent_http_content_type
    • sent_http_content_length
    • sent_http_location
    • sent_http_last_modified
    • sent_http_connection
    • sent_http_keep_alive
    • sent_http_transfer_encoding
    • sent_http_cache_control
    • sent_http_link

    通用:除了上面這些頭部,其餘的頭部都是通用型的,也就是能夠直接拿來用。

Nginx 系統變量

  • time_local:以本地時間標準輸出的當前時間,例如 14/Nov/2018:15:55:37 +0800
  • time_iso8601:使用 ISO8601 標準輸出的當前時間,例如 2018-11-14T15:55:37+08:00
  • nginx_version:Nginx 版本號
  • pid:所屬 worker 進程的進程 id
  • pipe:使用了管道則返回 p,不然返回 .
  • hostname:所在服務器的主機名,與 hostname 命令輸出一致
  • msec:1970 年 1 月 1 日到如今的時間,單位爲秒,小數點後精確到毫秒

實戰

配置文件:

log_format  vartest  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status bytes_sent=$bytes_sent body_bytes_sent=$body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$sent_http_abc"';

server {
    server_name var.ziyang.com localhost;
    #error_log logs/myerror.log debug;
    access_log logs/vartest.log vartest;
    listen 9090;

    location / {
        set $limit_rate 10k;
        # return 200; tcpinfo: $tcpinfo_rtt,$tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space 
        return 200 '
arg_a: $arg_a,arg_b: $arg_b,args: $args
connection: $connection,connection_requests: $connection_requests
cookie_a: $cookie_a
uri: $uri,document_uri: $document_uri, request_uri: $request_uri
request: $request
request_id: $request_id
server: $server_addr,$server_name,$server_port,$server_protocol

host: $host,server_name: $server_name,http_host: $http_host
limit_rate: $limit_rate
hostname: $hostname
content_length: $content_length
status: $status
body_bytes_sent: $body_bytes_sent,bytes_sent: $bytes_sent
time: $request_time,$msec,$time_iso8601,$time_local
';
    }    
}複製代碼

從上面這個配置文件中,咱們能夠看出來,返回的響應裏面包含了一系列的變量,實際驗證一下:

➜  test_nginx curl -H 'Content-Length: 0' -H 'Cookie: a=c1' 'localhost:9090?a=1&b=22'

arg_a: 1,arg_b: 22,args: a=1&b=22
connection: 2,connection_requests: 1
cookie_a: c1
uri: /,document_uri: /, request_uri: /?a=1&b=22
request: GET /?a=1&b=22 HTTP/1.1
request_id: 5d40b1ff29d2b87d5db5c4f95ebf5e4d
server: 127.0.0.1,var.ziyang.com,9090,HTTP/1.1
host: localhost,server_name: var.ziyang.com,http_host: localhost:9090
limit_rate: 10240
hostname: yuanzizhen.local
content_length: 0
status: 200
body_bytes_sent: 0,bytes_sent: 0
time: 0.000,1590842354.866,2020-05-30T20:39:14+08:00,30/May/2020:20:39:14 +0800複製代碼

你們能夠對比一下響應和配置文件中的值是否是一一對應的,更加深入的理解一下變量的含義。

好了,這一節我們學習了。關於 Nginx 的變量就講完了,下一節講一下實際應用變量的兩個模塊,你們會有更深入的理解。


本文首發於個人我的博客:iziyang.github.io,全部配置文件我已經放在了 Nginx 配置文件,你們能夠自取。

相關文章
相關標籤/搜索