Nginx-虚拟主机名称匹配规则
Nginx server_name:配置主机名称
语法 | server_name name ...; name可以提供多个中间用空格分隔 |
---|---|
作用域 | server |
server_name的配置方式有三种,分别是:
- 精准匹配
- 通配符匹配
- 正常表达式配置
补充小知识点:
hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。
所以我们可以使用修改hosts文件来制作一些虚拟域名来使用。
windows:C:\Windows\System32\drivers\etc centos:/etc/hosts
1. 精确匹配
server{ sever_name www.example.com www.example.cn; ... }
2. 使用通配符(* :可以匹配个多个单词)
server_name中支持通配符"*",但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段。有一种形如 ".example.org" 的特殊通配符,它可以既匹配确切的名字"example.org",又可以匹配一般的通配符名字 "*.example.org"。
server{ sever_name *.example.com www.example.* .example.com www.example.; ... }
匹配的url
- 前缀匹配 *.example.com;*: 表示前面可以匹配多个单词
- www.example.com,www.blog.example.com,www.blog.show.example.com ...
- 后缀匹配 www.example.*; *: 表示后面可以匹配多个单词
- www.example.com, www.example.com.cn.xyz, www.example.com.cn.xyz.org ...
3. 使用正则表达式配置
使用~作为正则表达式字符串的开始标记
使用~开头进行匹配,一般都写上^和$,来限定域名
正则中可以抓取变量部分,进行后面语法中的使用
如果在正则里面存在“{”和”}”,则需要将域名用引号引起来:
server{ listen 9091; sever_name "~^(?\w\d{1,3}+)\.example\.net$"; defalut_type text/plain; return 200 "name:$name"; }
正则内容捕获,也可以用常用的是用$number来表示
server{ server_name ~^(www\.)?(?.+)$; defalut_type text/plain; # $1 (www\.) $2 (.+) return 200 "$1$2"; }
如果配置完 重启,报错如下,则说明系统的PCRE库版本过旧需要更新
pcre_compile() failed: unrecognized character after (?< in ...
代码 | 说明 |
---|---|
^ | 匹配搜索字符串开始位置 |
$ | 匹配搜索字符串结束位置 |
. | 匹配除换行符\n之外的任何单个字符 |
\ |
转义字符,将下一个字符标记为特殊字符 |
[xyz] | 字符集,与任意一个指定字符匹配 |
[a- z] | 字符范围,匹配指定范围内的任何字符 |
\w | 与以下任意字符匹配 A-Z a-z 0-9 和下划线,等效于[A-Za-z0-9_] |
\d | 数字字符匹配,等效于[0-9] |
正好匹配n次 | |
至少匹配n次 | |
匹配至少n次至多m次 | |
* | 零次或多次,等效于 |
+ | 一次或多次,等效于 |
? | 零次或一次,等效于 |
匹配执行顺序
由于server_name指令支持通配符和正则表达式,因此在包含多个虚拟主机的配置文件中,可能会出现一个名称被多个虚拟主机的server_name匹配成功,当遇到这种情况,当前的请求交给谁来处理呢?
server{ listen 9091; sever_name ~^(www\.)?(.+)$; default_type text/plain; return 200 'regex_success'; } server{ listen 9091; server_name www.myweb.*; default_type text/plain; return 200 'wildcard_after_success'; } server{ listen 9091; server_name *.myweb.com; default_type text/plain; return 200 'wildcard_before_success'; } server{ listen 9091; server_name www.myweb.com; default_type text/plain; return 200 'exact_success'; } server{ listen 9091 default_server; server_name _; default_type text/plain; return 200 'default_server not found server!!'; }
结论
- exact_success 精准匹配
- wildcard_before_success 前通配符
- wildcard_after_success 后通配符
- regex_success 正则匹配
- default_server not found server!!
杂项
如果需要处理请求而没有默认的服务器块中的“主机”头字段,则应指定一个空名称:
如果在服务器块中没有定义server_name,那么nginx将使用空名作为服务器名称。
server { listen 80; server_name example.org www.example.org ""; ... }
在全部服务器示例中,可以看到奇怪的名称“_ ”:
这个名字没有什么特别之处,它只是无数个无效域名的其中一个,永远不会与任何真实姓名相交。其他无效名称,如“ –”和“ !@#”也可以同样使用。
表示:找不到任何配的主机名,就用这个默认的匹配的。
server { listen 80 default_server; server_name _; return 444; }
优化
- 精确匹配域名,泛域名,正则域名会对应创建三张表和侦听端口关联。
- 先搜索精确匹配表,然后泛域名表,最后搜索正则域名表。
- 泛域名表的查询比精确匹配表查询慢。
- 正则域名表则会依次查询,效率最低。
- 尽可能的采用精确匹配域名,来获得最大化效率
域名过长的情况
如果定义了一个过长的域名,则可能需要修改http上下文中
server_names_hash_max_size
和 server_names_hash_bucket_size 两个属性值,否则启动nginx会出现报错。
默认的 server_names_hash_max_size 和 server_names_hash_bucket_size 的值和环境中cpu cache line size相关,32或者64。
查看cpu cache line size可以用getconf命令:
getconf -a | grep -i _CACHE_LINESIZE LEVEL2_CACHE_LINESIZE 64 LEVEL3_CACHE_LINESIZE 64
如果服务器是监听端口的唯一服务器,则nginx将不会测试服务器名称(并且不会为监听端口构建哈希表)。但是有一个例外。如果服务器名称是带有捕获的正则表达式,则nginx必须执行表达式才能获取捕获。