Nginx-虚拟主机名称匹配规则

Nginx server_name:配置主机名称

语法 server_name name ...; name可以提供多个中间用空格分隔
作用域 server

server_name的配置方式有三种,分别是:

  1. 精准匹配
  2. 通配符匹配
  3. 正常表达式配置

补充小知识点:

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

  1. 前缀匹配 *.example.com;*: 表示前面可以匹配多个单词
    • www.example.com,www.blog.example.com,www.blog.show.example.com ...
  2. 后缀匹配 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!!';
}

结论

  1. exact_success 精准匹配
  2. wildcard_before_success 前通配符
  3. wildcard_after_success 后通配符
  4. regex_success 正则匹配
  5. 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必须执行表达式才能获取捕获。

posted @ 2021-11-28 11:17  BEJSON  阅读(490)  评论(0编辑  收藏  举报