編譯自:
http://nginx.org/en/docs/http/server_names.htmlhtml
目錄:
通配符主機名
正則表達式主機名
混雜主機名
對主機名的優化
兼容性nginx
nginx 的 server names 由 server_name 指令定義,server name 是 nginx 用於選擇以哪一個 server 區塊處理訪問請求的依據參數。可參考 《nginx 是如何處理請求的》 的描述。git
server name 能夠用三種方式定義:
定義準確的名字
定義通配符名字
定義正則表達式名字正則表達式
例如:緩存
server {
listen 80;
server_name example.org www.example.org;
...
}bash
server {
listen 80;
server_name *.example.org;
...
}dom
server {
listen 80;
server_name mail.*;
...
}測試
server {
listen 80;
server_name ~^(?<user>.+)\.example\.net$;
...
}優化
當 nginx 以請求的 server name 查找匹配的虛擬主機時,若是匹配的 server 區塊不止一個,nginx 按照以下的優先順序選擇 server 區塊:ui
1. 準確的主機名
2. 以 「*」 起始的最長的通配主機名
3. 以 「*」 結尾的最長的通配主機名
4. 第一個匹配的正則表達式(按照配置文件中的順序)
因此,若是同時有一個通配主機名和正則表達式主機名與訪問請求的 server name 匹配,nginx 會選擇通配主機名的 server 區塊處理請求。
通配主機名只能在起始和末尾使用 「*」 字符,並且必須以 「.」 分隔。形如 「www.*.example.org」 或者 「w*.example.org」 的通配主機名是無效的。要達到這個匹配效果,只有使用正則表達式:
"www.*.example.org" -> "~^www\..+\.example\.org$"
"w*.example.org" -> "~^w.*\.example\.org$"
「*」 號能夠匹配多個名字區域,「*.example.org」 不只能夠匹配 www.example.org,也可以匹配 www.sub.example.org。
nginx 使用的正則表達式與 Perl 語言的正則表達式(PCRE)兼容。使用正則表達式主機名,server name 必須以 「~」 字符爲起始字符。
server_name ~^www\d+\.example\.net$;
若是不以 「~」 字符爲起始字符,該 server name 將被視爲 「準確的主機名」 或者當 server name 包含 「*」 時被視爲 「通配主機名」 (多數狀況是非法通配主機名,由於只有當 「*」 在 server name 的起始或結尾時才合法)。
不要忘記設置 「^」 和 「$」 錨定符對主機名進行界定,這不是 nginx 的配置語法要求,而是爲了使正則表達式能正確匹配。
同時也要注意,域名的分隔符 「.」 在正則表達式中應該以 「\」 引用。若是在正則表達式中使用了 「{」 和 「}」 字符,應該將整個正則表達式引用起來,由於花括弧在 nginx 配置中也有特殊意義,引用起來以免被 nginx 錯誤解析。例如:
server_name "~^(?<name>\w\d{1,3}+)\.example\.net$";
若是不引用起來,nginx 會啓動失敗,並顯示以下錯誤信息:
directive "server_name" is not terminated by ";" in ...
正則表達式的 named capture (使用一個名字對匹配的字符串進行引用)可被視爲一個變量,在後面的配置中使用:
server {
server_name ~^(www\.)?(?<domain>.+)$;
location / {
root /sites/$domain;
}
}
PCRE 庫支持 named capture,有以下幾種語法:
?<name> Perl 5.10 compatible syntax, supported since PCRE-7.0
?'name' Perl 5.10 compatible syntax, supported since PCRE-7.0
?P<name> Python compatible syntax, supported since PCRE-4.0
可參考:http://www.pcre.org/current/doc/html/pcre2pattern.html#SEC16
\d any decimal digit
\w any "word" character
若是 nginx 啓動失敗,並顯示以下信息:
pcre_compile() failed: unrecognized character after (?< in ...
這表示 PCRE 庫太老舊,可嘗試使用 「?P<name>」 替代 「?<name>」。
named capture 也能以數字形式使用:
server {
server_name ~^(www\.)?(.+)$;
location / {
root /sites/$2;
}
}
不管如何,數字形式的使用應儘可能簡單,由於數字是隻是順序標識,而不是被匹配的字符串的標識,這致使數字引用很容易被覆蓋。
有一些主機名是被特殊對待的。
對於未定義 「Host」 請求首部的請求,若是但願在某個 server 區塊中處理這樣的請求,應在 server_name
指令的參數中添加 "" 空字符串參數:
server {
listen 80;
server_name example.org www.example.org "";
...
}
在《nginx 是如何處理訪問請求的》一文中曾經介紹過,若是 server 區塊中沒有定義 server_name 指令,便如同定義了 server_name ""。
Note:
在 0.8.48 版之前,遇到 server 區塊中沒有定義 server_name 指令的狀況,
會將系統的主機名設置爲 server 區塊的 server name,而不是自動設置 "" 爲
server name。
在 0.9.4 版本,若是設置:server_name $hostname,會將系統的主機名設置爲 server name。
若是某個訪問使用了 IP 地址 而不是 server name,「Host」 請求首部會包含 IP 地址。對於這樣的請求,
可以使用以下的配置:
server {
listen 80;
server_name example.org
www.example.org
""
192.168.1.1
;
...
}
下面是一個 catch-all server 區塊的配置,使用了 「_」 做爲 server name:
server {
listen 80 default_server;
server_name _;
return 444;
}
這個 server name 並無什麼特殊之處,它僅是一個無效的域名而已,也可使用其餘相似的名字,如 「--」 and 「!@#」 。0.6.25 版之前的 nginx 曾經支持一個特殊的 server name: 「*」,這個特殊主機名被錯誤的解釋成一個catch-all 主機名。但它從未以一個 catch-all 或者 通配主機名工做,它的功能實際上與如今的 server_name_in_redirect 指令的功能相同。
特殊的 server name 「*」 如今已經被棄用,應使用 server_name_in_redirect 指令。
要注意的是,使用 server_name 指令沒法指定 defalt server 或是 catch-all name,這是 listen 指令的屬性,不是 server_name 指令的屬性。可參考《nginx 是如何處理訪問請求的》。
咱們能夠定義兩個 server,它們都同時監聽於 *:80 端口 和 *:8080 端口,將其中一個設置爲 *:80 端口的默認 server,將另外一個設置爲 *:8080 端口的默認 server:
server {
listen 80;
listen 8080 default_server;
server_name example.net;
...
}
server {
listen 80 default_server;
listen 8080;
server_name example.org;
...
}
準確的主機名、以 「*」 起始的通配主機名、以 「*」 結尾的通配主機名,這三種主機名被存放在三個 hash table 中。這三個 hash table 是與監聽端口綁定的。hash table 的大小在配置階段
被優化,優化的目的是努力下降這些名字在 CPU 緩存中命中失敗的概率。關於設置 hash table 的詳細討論請參考:http://nginx.org/en/docs/hash.html
在匹配主機名時,首先查找「準確主機名」的 hash table,若是沒有找到,會查找以 「*」 起始的「通配主機名」的hash table,若是沒有仍未找到,會查找以 「*」 結尾的「通配主機名」的 hash table。
對於「通配主機名」的 hash table 的檢索會更慢,由於是以主機名的域名部分去檢索的。
注意,對於特殊的通配主機名,形如 「.example.org」,這樣的主機名是存放在「通配主機名」的 hash table 中,而不是存放在「準確主機名」的 hash table 中。
若是前面都未找到,正則表達式會按寫在配置文件中的順序被測試,所以正則表達式是最慢的方法,而且沒有可擴展性。
由於以上這些緣由,在可能的狀況下最好使用 「準確的主機名」。例如,若是對於 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 context 中調整這個兩個參數:
server_names_hash_max_size
server_names_hash_bucket_size
server_names_hash_bucket_size 指令的默認值可能爲 32 或 64 或 其餘數字,這是根據 CPU 緩存線大小而定的。若是默認值爲 32,並且定義了一個 server name 爲:「too.long.server.name.example.org」 這時 nginx 就不能啓動,並且顯示以下的錯誤信息:
could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
遇到這種狀況,應將默認值設置爲原來的兩倍:
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 的值,設置爲大於 server name 總數的值。若是這樣設置仍不能讓 nginx 正常啓動,或者 nginx 啓動的時間變得過長,再嘗試增長 server_names_hash_bucket_size 的值。
若是一個 server 是某個監聽端口惟一的 server,這時 nginx 根本不會去測試 server name,同時也不會爲該監聽端口構建 hash table。但其中又有一個例外,若是 server name 是正則表達式,並且正則表達式中包含了 captures,這時 nginx 不得不執行該正則表達式以獲取 captures。(正則表達式的 capture 是指被圓括號引用的表達式部分,它們所匹配的字符串,可經過名字或數字引用)
從 0.9.4 開始支持特殊主機名 「$hostname」
從 0.8.48 開始,若是 server 區塊中未定義 server_name 指令,nginx 默認設定空字符串爲主機名,如同定義了 server_name ""
從 0.8.25 開始支持在「正則表達式主機名」中使用 named capture 特性
從 0.7.40 開始支持在「正則表達式主機名」中使用 capture 特性
從 0.7.12 開始支持 "" 空字符串主機名
從 0.6.25 開始,支持使用「正則表達式主機名」或者「通配主機名」做爲第一個主機名。
從 0.6.7 開始支持「正則表達式主機名」
從 0.6.0 開始支持形如 example.* 的「通配主機名」
從 0.3.18 開始支持形如 .example.org 的特殊「通配主機名」
從 0.1.13 開始支持形如 *.example.org 的「通配主機名」
written by Igor Sysoev edited by Brian Mercer