伺服器名稱
萬用字元名稱 正規表示式名稱 其他名稱 國際化名稱 虛擬伺服器選擇 最佳化 相容性 |
伺服器名稱使用 server_name 指令定義,並決定針對特定請求使用哪個 server 區塊。另請參閱「nginx 如何處理請求」。它們可以使用確切名稱、萬用字元名稱或正規表示式來定義。
server { listen 80; server_name example.org www.example.org; ... } server { listen 80; server_name *.example.org; ... } server { listen 80; server_name mail.*; ... } server { listen 80; server_name ~^(?<user>.+)\.example\.net$; ... }
當依名稱搜尋虛擬伺服器時,如果名稱符合多個指定的變體,例如萬用字元名稱和正規表示式都符合,則會選擇第一個符合的變體,其優先順序如下:
- 確切名稱
- 以星號開頭的最長萬用字元名稱,例如「
*.example.org
」 - 以星號結尾的最長萬用字元名稱,例如「
mail.*
」 - 第一個符合的正規表示式(依組態檔中的顯示順序)
萬用字元名稱
萬用字元名稱只能在名稱的開頭或結尾包含星號,並且只能在點邊界上。名稱「www.*.example.org
」和「w*.example.org
」無效。但是,可以使用正規表示式來指定這些名稱,例如「~^www\..+\.example\.org$
」和「~^w.*\.example\.org$
」。一個星號可以符合多個名稱部分。名稱「*.example.org
」不僅符合 www.example.org
,也符合 www.sub.example.org
。
可以使用「.example.org
」形式的特殊萬用字元名稱,來同時符合確切名稱「example.org
」和萬用字元名稱「*.example.org
」。
正規表示式名稱
nginx 使用的正規表示式與 Perl 程式語言 (PCRE) 使用的正規表示式相容。若要使用正規表示式,伺服器名稱必須以波浪符號字元開頭。
server_name ~^www\d+\.example\.net$;
否則會將其視為確切名稱,或者如果運算式包含星號,則將其視為萬用字元名稱(而且很可能是一個無效的名稱)。請勿忘記設定「^
」和「$
」錨點。它們在語法上不是必需的,但在邏輯上是必需的。另請注意,網域名稱的點應使用反斜線逸出。包含字元「{
」和「}
」的正規表示式應加上引號。
server_name "~^(?<name>\w\d{1,3}+)\.example\.net$";
否則 nginx 將無法啟動並顯示錯誤訊息。
directive "server_name" is not terminated by ";" in ...
具名的正規表示式擷取可以在稍後作為變數使用。
server { server_name ~^(www\.)?(?<domain>.+)$; location / { root /sites/$domain; } }
PCRE 程式庫支援使用以下語法進行具名擷取:
如果 nginx 無法啟動並顯示錯誤訊息
?<
name
>Perl 5.10 相容語法,自 PCRE-7.0 起支援 ?'
name
'Perl 5.10 相容語法,自 PCRE-7.0 起支援 ?P<
name
>Python 相容語法,自 PCRE-4.0 起支援
pcre_compile() failed: unrecognized character after (?< in ...
這表示 PCRE 程式庫版本較舊,應嘗試使用語法「?P<
」。擷取也可以使用數位形式。name
>
server { server_name ~^(www\.)?(.+)$; location / { root /sites/$2; } }
但是,此類用法應僅限於簡單的情況(如上述),因為數位參考可能會輕易被覆寫。
其他名稱
有些伺服器名稱會受到特殊處理。
如果需要在非預設的 server 區塊中處理沒有「Host」標頭欄位的請求,則應指定空名稱。
server { listen 80; server_name example.org www.example.org ""; ... }
如果在 server 區塊中未定義 server_name,則 nginx 會使用空名稱作為伺服器名稱。
在 0.8.48 之前的 nginx 版本中,會在此情況下使用機器的hostname作為伺服器名稱。
如果伺服器名稱定義為「$hostname
」(0.9.4),則會使用機器的 hostname。
如果有人使用 IP 位址而不是伺服器名稱發出請求,「Host」請求標頭欄位將包含 IP 位址,並且可以使用 IP 位址作為伺服器名稱來處理請求。
server { listen 80; server_name example.org www.example.org "" 192.168.1.1 ; ... }
在 catch-all 伺服器範例中,可以看到奇怪的名稱「_
」。
server { listen 80 default_server; server_name _; return 444; }
這個名稱沒有什麼特別之處,它只是一個永遠不會與任何實際名稱相交的無效網域名稱。其他無效名稱,例如「--
」和「!@#
」也可以同樣使用。
在 0.6.25 之前的 nginx 版本中,支援特殊名稱「*
」,但被錯誤地解釋為 catch-all 名稱。它從未作為 catch-all 或萬用字元伺服器名稱運作。相反,它提供了現在由 server_name_in_redirect 指令提供的功能。特殊名稱「*
」現在已過時,應使用 server_name_in_redirect 指令。請注意,無法使用 server_name 指令指定 catch-all 名稱或預設伺服器。這是 listen 指令的屬性,而不是 server_name 指令的屬性。另請參閱「nginx 如何處理請求」。可以定義在連接埠 *:80 和 *:8080 上接聽的伺服器,並指定其中一個將成為連接埠 *:8080 的預設伺服器,而另一個將成為連接埠 *:80 的預設伺服器。
server { listen 80; listen 8080 default_server; server_name example.net; ... } server { listen 80 default_server; listen 8080; server_name example.org; ... }
國際化名稱
國際化網域名稱 (IDN) 應在 server_name 指令中使用 ASCII (Punycode) 表示法指定。
server { listen 80; server_name xn--e1afmkfd.xn--80akhbyknj4f; # пример.испытание ... }
虛擬伺服器選擇
首先,會在預設伺服器內容中建立連線。然後,可以在以下請求處理階段中確定伺服器名稱,每個階段都參與伺服器組態選擇:
-
在 SSL 交握期間,根據 SNI 預先進行
-
在處理請求行之後
-
在處理
Host
標頭欄位之後 -
如果在處理請求行或從
Host
標頭欄位之後未確定伺服器名稱,nginx 將使用空名稱作為伺服器名稱。
在這些階段中的每一個階段,都可以套用不同的伺服器組態。因此,應謹慎指定某些指令:
- 在 ssl_protocols 指令的情況下,通訊協定清單由 OpenSSL 程式庫設定,然後才能根據透過 SNI 要求的名稱套用伺服器組態,因此,通訊協定應僅針對預設伺服器指定;
- client_header_buffer_size 和 merge_slashes 指令在讀取請求行之前就會參與,因此,此類指令會使用預設伺服器組態或 SNI 選取的伺服器組態;
- 在處理請求標頭欄位的 ignore_invalid_headers、large_client_header_buffers 和 underscores_in_headers 指令的情況下,這也取決於是否已根據請求行或
Host
標頭欄位更新伺服器組態; - 錯誤回應將使用目前履行請求的伺服器中的 error_page 指令處理。
最佳化
確切名稱、以星號開頭的萬用字元名稱以及以星號結尾的萬用字元名稱儲存在繫結到接聽連接埠的三個雜湊表中。雜湊表的大小會在組態階段進行最佳化,以便可以以最少的 CPU 快取遺失次數找到名稱。設定雜湊表的詳細資訊會在單獨的文件中提供。
首先會搜尋確切名稱雜湊表。如果找不到名稱,則會搜尋以星號開頭的萬用字元名稱雜湊表。如果在那裡找不到名稱,則會搜尋以星號結尾的萬用字元名稱雜湊表。
搜尋萬用字元名稱雜湊表的速度比搜尋確切名稱雜湊表慢,因為名稱是按網域部分搜尋的。請注意,特殊的萬用字元形式「.example.org
」會儲存在萬用字元名稱雜湊表中,而不是確切名稱雜湊表中。
正規表示式會依序測試,因此是最慢的方法,且無法擴充。
由於這些原因,最好盡可能使用確切名稱。例如,如果伺服器最常請求的名稱是 example.org
和 www.example.org
,則明確定義它們會更有效率。
server { listen 80; server_name example.org www.example.org *.example.org; ... }
而不是使用簡化形式。
server { listen 80; server_name .example.org; ... }
如果定義了大量的伺服器名稱,或定義了異常長的伺服器名稱,則可能需要在 http 層級調整 server_names_hash_max_size 和 server_names_hash_bucket_size 指令。server_names_hash_bucket_size 指令的預設值可能等於 32、64 或其他值,具體取決於 CPU 快取行大小。如果預設值為 32,並且伺服器名稱定義為「too.long.server.name.example.org
」,則 nginx 將無法啟動並顯示錯誤訊息。
could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
在此情況下,指令值應增加到下一個 2 的冪次。
http { server_names_hash_bucket_size 64; ...
如果定義了大量的伺服器名稱,則會顯示另一個錯誤訊息。
could not build the server_names_hash, you should increase either server_names_hash_max_size: 512 or server_names_hash_bucket_size: 32
在這種情況下,請先嘗試將 server_names_hash_max_size 設定為接近伺服器名稱數量的數字。只有在這樣做沒有幫助,或者 nginx 的啟動時間太長時,才嘗試增加 server_names_hash_bucket_size。
如果伺服器是接聽連接埠的唯一伺服器,則 nginx 將完全不會測試伺服器名稱(也不會為接聽連接埠建立雜湊表)。但是,有一個例外。如果伺服器名稱是帶有擷取的正規表示式,則 nginx 必須執行運算式才能取得擷取。
相容性
- 自 0.9.4 起,即支援特殊伺服器名稱「
$hostname
」。 - 自 0.8.48 起,預設伺服器名稱值為空名稱「」。
- 自 0.8.25 起,支援具名的正規表示式伺服器名稱擷取。
- 自 0.7.40 起,支援正規表示式伺服器名稱擷取。
- 自 0.7.12 起,支援空伺服器名稱「」。
- 自 0.6.25 版本起,已支援使用萬用字元伺服器名稱或正規表示式作為第一個伺服器名稱。
- 自 0.6.7 版本起,已支援正規表示式伺服器名稱。
- 自 0.6.0 版本起,已支援萬用字元形式
example.*
。 - 自 0.3.18 版本起,已支援特殊形式
.example.org
。 - 自 0.1.13 版本起,已支援萬用字元形式
*.example.org
。
作者:Igor Sysoev 編輯:Brian Mercer |