nginx学习笔记(8)虚拟主机名---转载
| 通配符名字 正則表達式名字 其他類型的名字 優化 兼容性 |
虛擬主機名使用server_name指令定義,用于決定由某臺虛擬主機來處理請求。具體請參考《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$;... }nginx以名字查找虛擬主機時,如果名字可以匹配多于一個主機名定義,比如同時匹配了通配符的名字和正則表達式的名字,那么nginx按照下面的優先級別進行查找,并選中第一個匹配的虛擬主機:
通配符名字
通配符名字只可以在名字的起始處或結尾處包含一個星號,并且星號與其他字符之間用點分隔。所以,“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使用的正則表達式兼容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> | 從PCRE-7.0開始支持,兼容Perl 5.10語法 |
| ?'name' | 從PCRE-7.0開始支持,兼容Perl 5.10語法 |
| ?P<name> | 從PCRE-4.0開始支持,兼容Python語法 |
如果nginx不能啟動,并顯示錯誤信息:
pcre_compile() failed: unrecognized character after (?< in ...說明PCRE版本太舊,應該嘗試使用?P<name>。捕獲組也可以以數字方式引用:
server {server_name ~^(www\.)?(.+)$;location / {root /sites/$2;} }不過,這種用法只限于簡單的情況(比如上面的例子),因為數字引用很容易被覆蓋。
其他類型的名字
有一些主機名會被特別對待。
如果需要用一個非默認的虛擬主機處理請求頭中不含“Host”字段的請求,需要指定一個空名字:
server {listen 80;server_name example.org www.example.org "";... }如果server塊中沒有定義server_name,nginx使用空名字作為虛擬主機名。
nginx 0.8.48版本以下(含)在同樣的情況下會使用機器名作為虛擬主機名。如果以“$hostname”(nginx 0.9.4及以上版本)定義虛擬主機名,機器名將被使用。
如果使用IP地址而不是主機名來請求服務器,那么請求頭的“Host”字段包含的將是IP地址。可以將IP地址作為虛擬主機名來處理這種請求:
server {listen 80;server_name nginx.orgwww.nginx.org""192.168.1.1;... }在匹配所有的服務器的例子中,可以見到一個奇怪的名字“_”:
server {listen 80 default_server;server_name _;return 444; }這沒什么特別的,它只不過是成千上萬的與真實的名字絕無沖突的非法域名中的一個而已。當然,也可以使用“--”和“!@#”等等。
nginx直到0.6.25版本還支持一個特殊的名字“*”,這個名字一直被錯誤地理解成是一個匹配所有的名字。但它從來沒有像匹配所有的名字,或者通配符那樣工作過,而是用來支持一種功能,此功能現在已經改由server_name_in_redirect指令提供支持了。所以,現在這個特殊的名字“*”已經過時了,應該使用server_name_in_redirect指令取代它。需要注意的是,使用server_name指令無法描述匹配所有的名字或者默認服務器。這是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;... }優化
確切名字和通配符名字存儲在哈希表中。哈希表和監聽端口關聯。哈希表的尺寸在配置階段進行了優化,可以以最小的CPU緩存命中失敗來找到名字。設置哈希表的細節參見這篇文檔
nginx首先搜索確切名字的哈希表,如果沒有找到,搜索以星號起始的通配符名字的哈希表,如果還是沒有找到,繼續搜索以星號結束的通配符名字的哈希表。
因為名字是按照域名的節來搜索的,所以搜索通配符名字的哈希表比搜索確切名字的哈希表慢。注意特殊的通配符名字“.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出現了這種情況,那就需要將指令的值擴大一倍:
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_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 翻譯: cfsego |
轉載于:https://www.cnblogs.com/davidwang456/p/3428255.html
總結
以上是生活随笔為你收集整理的nginx学习笔记(8)虚拟主机名---转载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx学习笔记(7)Nginx如何处
- 下一篇: nginx 学习笔记(9) 配置HTTP