伺服器名稱

萬用字元名稱
正規表示式名稱
其他名稱
國際化名稱
虛擬伺服器選擇
最佳化
相容性

伺服器名稱使用 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$;
    ...
}

當依名稱搜尋虛擬伺服器時,如果名稱符合多個指定的變體,例如萬用字元名稱和正規表示式都符合,則會選擇第一個符合的變體,其優先順序如下:

  1. 確切名稱
  2. 以星號開頭的最長萬用字元名稱,例如「*.example.org
  3. 以星號結尾的最長萬用字元名稱,例如「mail.*
  4. 第一個符合的正規表示式(依組態檔中的顯示順序)

萬用字元名稱

萬用字元名稱只能在名稱的開頭或結尾包含星號,並且只能在點邊界上。名稱「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 程式庫支援使用以下語法進行具名擷取:

?<name> Perl 5.10 相容語法,自 PCRE-7.0 起支援
?'name' Perl 5.10 相容語法,自 PCRE-7.0 起支援
?P<name> Python 相容語法,自 PCRE-4.0 起支援
如果 nginx 無法啟動並顯示錯誤訊息

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;  # пример.испытание
    ...
}

虛擬伺服器選擇

首先,會在預設伺服器內容中建立連線。然後,可以在以下請求處理階段中確定伺服器名稱,每個階段都參與伺服器組態選擇:

在這些階段中的每一個階段,都可以套用不同的伺服器組態。因此,應謹慎指定某些指令:

最佳化

確切名稱、以星號開頭的萬用字元名稱以及以星號結尾的萬用字元名稱儲存在繫結到接聽連接埠的三個雜湊表中。雜湊表的大小會在組態階段進行最佳化,以便可以以最少的 CPU 快取遺失次數找到名稱。設定雜湊表的詳細資訊會在單獨的文件中提供。

首先會搜尋確切名稱雜湊表。如果找不到名稱,則會搜尋以星號開頭的萬用字元名稱雜湊表。如果在那裡找不到名稱,則會搜尋以星號結尾的萬用字元名稱雜湊表。

搜尋萬用字元名稱雜湊表的速度比搜尋確切名稱雜湊表慢,因為名稱是按網域部分搜尋的。請注意,特殊的萬用字元形式「.example.org」會儲存在萬用字元名稱雜湊表中,而不是確切名稱雜湊表中。

正規表示式會依序測試,因此是最慢的方法,且無法擴充。

由於這些原因,最好盡可能使用確切名稱。例如,如果伺服器最常請求的名稱是 example.orgwww.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_sizeserver_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 必須執行運算式才能取得擷取。

相容性

作者:Igor Sysoev
編輯:Brian Mercer