Nginx-服務器名稱

服務器名稱使用server_name指令來定義,確定請求使用哪個server塊。可以使用確切的名稱、通配符名稱或正則表達式來定義它們:

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\.orgKaTeX parse error: Undefined control sequence: \* at position 8: ”和“~^w.\̲*̲\\.example\\.or…”。星號可以匹配多個名稱部分,例如:“*.example.org”不僅匹配“www.example.org”,而且匹配“www.sub.example.org”

另外,還有一種特殊的通配符形式“.example.org”,他既可以匹配“example.org”,也可以匹配“*.example.org”

正則表達式名稱

Nginx使用的正則表達式與Perl編程語言使用的正則表達式兼容。要使用正則表達式,server_name指令的值必須以“~”開頭:

server_name ~^www\d+\.example\.net$;

否則,它將被視爲確切的名稱,或者如果表達式包含星號,則被視爲通配符名稱(並且很可能是無效的名稱)。不要忘記設置“^”和“$”錨。他們在語法上不是必須的,但是在邏輯上是必須的。還有一點需要注意,域名中的點應該使用反斜杆轉義。一個包含字符“{”和“}”的正則表達式應該使用引號包裹:

server_name "~^(?<name>\w\d{1, 3}+)\.example\.net$";

否則,Nginx將無法啓動並顯示錯誤信息。正則表達式匹配的內容可以被捕捉爲變量使用,如下:

server {
    server_name ~^(www\.)?(?<domain>.+)$;
    location / {
        root /sites/$domain;
    }
}

PCRE庫支持以下語法命名捕捉:

  • ?<name>: Perl5.10兼容語法,自PCRE-7.0起受支持
  • ?'name': Perl5.10兼容語法,自PCRE-7.0起受支持
  • ?P<name>: 自PCRE-4.0起受支持的Python兼容語法

如果Nginx無法啓動並顯示錯誤信息:

pcre_compile() failed: unrecognized character after (?< in ...

這意味着PCRE庫很老舊,應嘗試使用?P<name>替代。

正則表達式匹配的內容捕捉,也可以使用數字形式,如下:

server {
    server_name ~^(www\.)?(.+)$;
    location / {
        root /site/$2;
    }
}

其中“$2”表示正則表達式中匹配到的第二個內容。上面栗子中,如下傳遞的“Host”爲“www.baidu.com”,那麼匹配到“$2”將會是“baidu.com”。

雜項名稱

如果需要server塊中處理沒有“Host”標頭字段的額請求,則應指定空名稱:

server {
    listen 80;
    server_name example.org www.example.org "";
    ...
}

如果在server塊中未定義server_name,則Nginx使用空名稱作爲服務器名稱。

如果server_name定義爲$hostname,則使用計算機的主機名。

如果有人使用IP地址而不是服務器名發出的請求,“Host”請求標頭字段將包含IP地址,可以使用IP地址作爲服務器名處理請求。如下:

server {
    listen 80;
    server_name example.org www.example.org "" 192.168.1.1;
}

在所有的服務器示例中,你會看到一個其他的名稱“_”,如下:

server {
    listen 80 default_server;
    server_name _;
    rerturn 444;
}

這個名稱沒有什麼特別之處,它只是無數無效域名中的一個,這些域名與任何真實的名稱都沒有交集。同樣也可以使用其他的無效名稱,例如:“–”和“!@#”

國際化名稱

應在server_name指令中使用ASCII表示來指定國際化域名:

server {
    listen 80;
    server_name xn--e1afmkfd.xn--80akhbyknj4f;
    ...
}

優化

確切的名稱、以星號開頭的通配符名稱和以星號結尾的通配符名稱存儲在綁定到偵聽端口的三個哈希表中。哈希表的大小在配置階段進行了優化,以便能夠以最少的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_sizeserver_names_hash_bucket_size指令。server_names_hash_bucket_size指令的默認值可能是32、64或其他值,這取決於CPU緩存線的大小。如果定義了異常長的服務器名稱,導致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指令的值。

發佈了158 篇原創文章 · 獲贊 115 · 訪問量 52萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章