NGINX 作為網頁伺服器和反向代理伺服器,其 HTTP 組態設定是建構高效能網路服務的關鍵。本文將探討 HTTP/2 模組變數、HTTP 核心模組變數,以及 Location 區塊的應用。理解這些組態元素,能讓我們更精確地控制請求處理流程,並根據不同需求調整 NGINX 的行為。首先,我們會介紹 HTTP/2 模組中的 $http2 變數,用於判斷連線是否使用 HTTP/2 協定,並示範如何根據此變數進行流量重定向,確保客戶端能使用最佳的協定版本。接著,文章會探討 HTTP 核心模組中重要的變數,例如 $http_user_agent$remote_addr 等,說明如何利用這些變數擷取客戶端資訊,例如瀏覽器型別、IP 位址等,並根據這些資訊進行客製化處理,例如根據裝置型別提供不同內容、根據 IP 位址進行地域限制等。最後,我們將深入 Location 區塊的設定,包含各種比對規則和修飾符,例如 =^~~~*@,並搭配實際案例說明如何使用正規表示式比對 URL、設定優先順序、建立內部重定向等,以實作更複雜的路由和流量控制策略。

NGINX HTTP 組態深度探討

NGINX 作為一個強大的網頁伺服器和反向代理伺服器,其 HTTP 組態內容非常豐富。這篇文章將探討 NGINX 的 HTTP/2 模組變數、HTTP 核心模組變數及其應用。我們將從 HTTP/2 模組開始,進一步探討 HTTP 核心模組中的變數,並提供實際案例來說明如何應用這些變數。

HTTP/2 模組變數

HTTP/2 模組在 NGINX 中主要透過一個變數來控制是否使用 HTTP/2:

  • $http2:如果使用 TLS 進行的 HTTP/2,則傳回 h2;如果是明文 TCP 的 HTTP/2,則傳回 h2c;如果未使用 HTTP/2,則傳回空字串。

透過這個變數,我們可以輕鬆地判斷當前連線是否使用了 HTTP/2。

實務案例:檢查 HTTP/2 支援

在某些情況下,我們可能需要根據客戶端是否支援 HTTP/2 來進行不同的處理。例如,可以根據 $http2 變數的值來重定向流量:

server {
    listen 443 ssl http2;
    server_name example.com;

    location / {
        if ($http2 = '') {
            return 301 https://example.com;
        }
        # 其他處理邏輯
    }
}
小段落標題:HTTP/2 模組變數應用

在這個案例中,當 $http2 的值為空字串時,表示客戶端不支援 HTTP/2,因此我們重定向到另一個支援 HTTP/1.1 的 URL。這樣可以確保相容性,同時利用現代化的 HTTP/2 特性。

客戶端請求標頭變數

NGINX 提供了一系列變數來存取客戶端請求的標頭資訊。這些變數可以在組態中使用,以便進行更靈活的組態和處理。

  • $http_host:存取 Host 標頭的值。
  • $http_user_agent:存取 User-Agent 標頭的值。
  • $http_referer:存取 Referer 標頭的值。
  • $http_via:存取 Via 標頭的值。
  • $http_x_forwarded_for:存取 X-Forwarded-For 標頭的值,這對於反向代理非常有用。
  • $http_cookie:存取 Cookie 標頭的值。

實務案例:根據 User-Agent 處理不同裝置

在某些情況下,我們需要根據客戶端的裝置型別來提供不同的內容。例如,可以根據 User-Agent 標頭來區分行動裝置和桌面電腦:

server {
    listen 80;
    server_name example.com;

    location / {
        if ($http_user_agent ~* "Mobile") {
            proxy_pass http://mobile.example.com;
        } else {
            proxy_pass http://desktop.example.com;
        }
    }
}
小段落標題:User-Agent 處理策略

在這個案例中,我們使用正規表示式比對 User-Agent 標頭中的關鍵字 “Mobile”,並根據結果將流量轉發到不同的後端伺服器。這樣可以確保不同裝置獲得最佳化的體驗。

NGINX 生成的標頭變數

除了請求標頭之外,NGINX 還提供了一些自動生成的變數,這些變數涵蓋了請求處理過程中的各種細節。

  • $arg_XXX:存取查詢字串引數。
  • $binary_remote_addr:客戶端 IP 地址(二進位制形式)。
  • $body_bytes_sent:已傳送的回應主體位元組數。
  • $bytes_sent:已傳送給客戶端的總位元組數。
  • $connection_requests:當前連線已處理的請求數量。

實務案例:限制速率

在某些情況下,我們需要限制每個連線的傳輸速率。例如,可以使用 $connection_requests$bytes_sent 來限制每個連線傳送的位元組數:

server {
    listen 80;
    server_name example.com;

    location / {
        limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
        limit_req zone=one burst=5 nodelay;
    }
}
小段落標題:限速策略

在這個案例中,我們使用 limit_req_zonelimit_req 指令來限制每秒每個 IP 地址只能發起一個請求。當連線超過限制時,會自動延遲或拒絕額外的請求。

命令列解析與分析

透過以上變數及其應用案例,玄貓相信大家對 NGINX 的 HTTP 組態有了更深入的瞭解。這些變數不僅能夠幫助我們更靈活地處理請求和回應,還能提升系統的安全性和效能。希望這篇文章能夠幫助大家在實際操作中更好地應用這些技術。

NGINX 內建變數與 Location 區塊的探討

在現代網路服務中,NGINX 作為一個強大且靈活的反向代理伺服器和負載平衡器,其組態的細緻程度可以達到極高的層次。本文將探討 NGINX HTTP 核心模組中的內建變數,並詳細說明如何利用 Location 區塊來精確控制請求處理流程。

變數的應用與意義

NGINX 提供了豐富的內建變數,這些變數可以用來取得請求和伺服器的各種資訊。以下是一些常見且實用的變數及其描述:

  • $msec:傳回當前時間(以秒和毫秒為單位)。
  • $nginx_version:傳回正在執行的 NGINX 版本。
  • $pid:傳回 NGINX 程式識別碼。
  • $pipe:如果當前請求是管道化的,則設定為 p;否則為空字串。
  • $proxy_protocol_addr:如果在 listen 指令中啟用了 proxy_protocol 引數,則包含客戶端地址。
  • $query_string:與 $args 相同,傳回請求中的查詢字串。
  • $remote_addr:傳回客戶端的 IP 地址。
  • $remote_port:傳回客戶端通訊端的埠號。
  • $remote_user:如果客戶端使用了驗證,則傳回使用者名稱。
  • $realpath_root:傳回客戶端請求中的檔案根目錄,並解析符號連線到實際路徑。
  • $request_body:傳回客戶端請求的主體部分,或如果主體為空則為 -
  • $request_body_file:如果請求主體被儲存(參見 client_body_in_file_only 指令),則指示臨時檔案的路徑。
  • $request_completion:如果請求已完成,則傳回 OK;否則為空字串。
  • $request_filename:傳回當前請求中所服務的完整檔名稱。
  • $request_length:傳回客戶端請求的總長度。
  • $request_method:指示請求中使用的 HTTP 方法,如 GETPOST.
  • $request_time:從讀取第一個位元組以來經過的時間(秒和毫秒值)。
  • $request_id:從 16 個隨機位元組生成的唯一請求識別碼,以十六進製表示。
  • $request_uri:對應於原始請求的 URI;在整個過程中保持不變(與 $document_uri/$uri 不同)。
  • $scheme:根據請求傳回 httphttps.
  • $server_addr:傳回伺服器的 IP 地址。需要注意的是,每次使用該變數都需要進行系統呼叫,這可能會影響高流量佈局下的整體效能。

說明變數如何應用於實務案例

假設我們有一個電子商務網站,需要根據客戶端的 IP 地址來進行地域限制。我們可以利用 $remote_addr$geoip_country_code 等變數來實作這一功能。以下是一個簡單的組態範例:

geo $geoip_country_code $allowed {
    default     no;
    US          yes;
    CA          yes;
}

server {
    listen       80;
    server_name  example.com;

    location / {
        if ($allowed = no) {
            return 403;
        }
        proxy_pass http://backend;
    }
}

Location 區塊的深入理解

NGINX 的組態可以細分到三個層級:協定層級(http 塊)、伺服器層級(server 塊)以及請求 URI 層級(location 塊)。location 塊允許我們根據請求 URI 的不同模式來定義特定的組態。

Location 區塊語法與修飾符

location 塊允許我們透過指定模式來比對請求 URI:

location [=|~|~*|^~|@] 模式 {
    # 組態
}

其中,第一個可選引數是 location 運算元,它定義了 NGINX 比對指定模式的方式以及模式本身的性質(簡單字串或正規表示式)。以下是一些常見的修飾符及其行為:

= 運算元

要求 URI 必須與指定模式完全比對。模式僅限於簡單字面字串,不允許使用正規表示式:

server {
    server_name website.com;
    location = /abcd {
        # 組態僅適用於 http://website.com/abcd
    }
}

無運算元

要求 URI 必須以指定模式開頭。不允許使用正規表示式:

server {
    server_name website.com;
    location /abcd {
        # 組態適用於 http://website.com/abcd、http://website.com/abcd/ 和 http://website.com/abcde
    }
}

~ 運算元

要求 URI 必須與指定正規表示式進行大小寫敏感比對:

server {
    server_name website.com;
    location ~ ^/abcd$ {
        # 組態僅適用於 http://website.com/abcd
    }
}

~* 運算元

要求 URI 必須與指定正規表示式進行大小寫不敏感比對:

server {
    server_name website.com;
    location ~* ^/abcd$ {
        # 組態適用於 http://website.com/abcd 和 http://website.com/ABCD
    }
}

應使用案例項分析

假設我們有一個多語言網站,需要根據不同語言版本來分發請求。我們可以利用 location 區塊來實作這一功能:

server {
    listen       80;
    server_name  example.com;

    location ~* ^/en/ {
        proxy_pass http://backend_en;
    }

    location ~* ^/zh/ {
        proxy_pass http://backend_zh;
    }

    location / {
        proxy_pass http://backend_default;
    }
}

此圖示展示了多語言網站如何根據語言版本進行請求分發:

  graph TD;
A[Client Request] --> B{Language Code};
B -->|en| C[Proxy to English Backend];
B -->|zh| D[Proxy to Chinese Backend];
B -->|Other| E[Proxy to Default Backend];

此圖示中的每一個步驟都清晰地展示了根據不同語言版本進行請求分發的一個過程。

NGINX Location Block 探討與實務應用

NGINX 作為一個高效能的反向代理伺服器,其組態中最重要的一部分就是 location block。location block 允許你定義如何處理不同的 URL 路徑,這在設計複雜的網站和應用時非常關鍵。以下將探討 location block 的各種修飾符及其應用場景。

正規表示式在 location block 中的應用

在 location block 中,正規表示式可以用來比對特定的 URL 模式。例如,以下正規表示式可以比對特定的 URL:

location ~ ^/abcd$ {
    # 這裡放置處理 /abcd 的邏輯
}

這個組態具有以下屬性:

  • 應用於 http://website.com/abcd(精確比對)
  • 應用於 http://website.com/ABCD(不區分大小寫)
  • 應用於 http://website.com/abcd?param1&param2(忽略查詢字串引數)
  • 不應用於 http://website.com/abcd/(結尾有斜槓,因為正規表示式不比對)
  • 不應用於 http://website.com/abcde(額外字元,因為正規表示式不比對)

內容解密:

這段程式碼中使用了正規表示式來精確比對 /abcd。正規表示式 ^/abcd$ 表示從頭到尾都必須是 /abcd,而不包含其他字元或結尾斜槓。NGINX 在處理請求時會根據這個正規表示式來決定是否比對並進行相應的處理。

^~ 修飾符的作用

^~ 修飾符的行為類別似於沒有修飾符的情況下,但如果模式比對,NGINX 會停止搜尋其他模式。這在你需要確保某個模式優先比對時非常有用。

location ^~ /files/ {
    # 應用於所有以 /files/ 開頭的請求
}

內容解密:

這段程式碼使用了 ^~ 修飾符,確保當請求的 URI 以 /files/ 開頭時,這個 location block 會優先比對並停止進一步搜尋其他模式。這對於需要高優先順序處理某些路徑的情況非常有幫助。

@ 修飾符的作用

@ 修飾符定義了一個命名的 location block,這些 block 不能被客戶端直接存取,只能由內部請求(如 try_fileserror_page)生成。

location @fallback {
    # 內部請求處理邏輯
}

內容解密:

這段程式碼定義了一個命名的 location block @fallback,它只能被內部請求呼叫。這在需要進行錯誤頁面重定向或檔案伺服時非常有用。

搜尋順序與優先順序

當 NGINX 接收到一個請求時,它會根據以下順序搜尋最佳比對的 location block:

  1. 帶有 = 的 location block:如果 URI 恰好比對,則保留。
  2. 沒有修飾符的 location block:如果 URI 恰好比對,則保留。
  3. 帶有 ^~ 的 location block:如果 URI 比對開頭部分,則保留。
  4. 帶有 ~~* 的 location block:如果正規表示式比對,則保留。
  5. 沒有修飾符且 URI 比對開頭部分的 location block:如果沒有更好的比對,則保留。

案例分析

案例一

假設有兩個 location block,一個以 /doc 開頭,另一個精確比對 /document

server {
    server_name website.com;
    location /doc {
        # 應用於以 /doc 開頭的請求
    }
    location ~* ^/document$ {
        # 應用於精確比對 /document 的請求
    }
}

當客戶端請求 http://website.com/document 時,雖然兩者都能比對該請求,但由於 ~* 的優先順序較高,所以第二個 location block 被選擇。

案例二

假設有兩個 location block,一個以 /document 開頭,另一個精確比對 /document

server {
    server_name website.com;
    location /document {
        # 應用於以 /document 開頭的請求
    }
    location ~* ^/document$ {
        # 應用於精確比對 /document 的請求
    }
}

當客戶端請求 http://website.com/document 時,第一個 location block 與請求完全比對(包含查詢字串),因此 NGINX 優先選擇第一個。

案例三

假設有兩個 location block,一個以 /doc 開頭且使用 ^~ 修飾符,另一個精確比對 /document

server {
    server_name website.com;
    location ^~ /doc {
        # 應用於以 /doc 開頭的請求
    }
    location ~* ^/document$ {
        # 應用於精確比對 /document 的請求
    }
}

當客戶端請求 http://website.com/document 時,由於 ^~ 的優先順序較高,第一個 location block 被選擇。