总结
豆包 AI 助手文章总结

Nginx虚拟服务器域名配置方法

小云云
发布: 2018-03-27 14:32:34
原创
3302人浏览过

本文主要和大家分享Nginx虚拟服务器域名配置方法,虚拟服务器名(server name)是通过指令server_name来指定的。在《 Nginx是如何处理Request的?》一节中,我们讲到nginx分两步来匹配过来的Request请求:

1.选择server

2.选择location

在第1步中,其实也分两步:

1).匹配port

2).匹配server_name

这一节就来聊聊nginx是如何具体匹配server_name的。

server_name指令

server_name的形式有三种:

1.精确域名形式(exact names)

2.通配符(*)形式

3.正则表达式形式

如下:

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$;
    ...
}
登录后复制

通配符形式,其实又分为前向通配符后向通配符(分别如第二,第三个例子),通配符不能位于字符串的中间位置。


当然,完全存在这么一种情况,一个host同时匹配上面三种的一种或者多种形式,比如host 为www.example.com可以同时匹配;

server_name   *.example.com *.com www.example.com  www.example.*  www.*   ~^(.+)\.example\.com$  

server_name  有6个指令参数,www.example.com都是匹配的,那么最后选择哪一个呢?有一定的顺序:


  1. 精确域名匹配www.example.com 

  2. 以通配符*开始的,最长的那个域名,*.example.com

  3. 以通配符*结束的,最长的那个域名,www.example.*

  4. 最后是正则表达式形式的,按照在配置文件中出现的顺序,依次尝试进行匹配,选取第一个被匹配到的域名,~^(.+)\.example\.com$


精确域名形式非常简单,接下来分别对server_name的通配符和正则表达式两种形式做个介绍。


通配符

通配符*在server name中的使用非常严格:只能位于域名的头部或者尾部,不能出现在中间;并且必须以"."分隔开

*.example.com

www.example.*

以下都是不合法的形式:

www.*.example.org

w*.example.org

当然,如果要达到后两者所体现的目的,可以使用正则表达式,例如,上面不合法的两个域名可以写成这样:

~^www\..+\.example\.org$

~^w.*\.example\.org$


另外一种特殊的形式可以同时匹配example.org和*.example.org,这就是

.example.org


正则表达式

nginx的正则表达式语法使用的是Perl语言(PCRE)的正则语法。基本形式为

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

这则表达式需要注意的几点


  • 必须以~开始,没有~符号的要么被视作完全匹配或者通配符匹配

  • ~和正则表达式主体之间没有空格

  • 正则表达式主体通常以^开始以$结束(虽说语法上不一定要求如此,但是从逻辑意义上强烈要求这么做)。

  • 正则表达式中,点号"."必须转义,写作"\.";正则表达式可以不用引号包住,但是,如果其中包含"{"和"}"则必须用双引号包裹

例如:

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

如果不加引号,nginx便无法正确加载配置文件,并报一个错误:

directive "server_name" is not terminated by ";" in ...


正则表达式使用命名捕获组,例如:

server {
    server_name ~^(?<myname>.+)\.example\.cn$;
    root /var/www/hb/$myname;   
}
登录后复制


PCRE语法支持下面几种捕获语法:

?<name>
?'name'
?P<name>
登录后复制

前面两者是最新的语法,第三种是老的写法。如果nginx报下面错误:

pcre_compile() failed: unrecognized character after (?

说明,你应该将?或者?'name'改为较古老的?P写法了。


同样,使用普通捕获组也是可以的:

server {
    server_name ~^(.+)\.example\.cn$;
    root /var/www/hb/$1;  
}
登录后复制

当然,普通捕获组要慎用,因为很容易被后面的正则所覆盖。


其他形式

除了两面提到的几种形式,sername_name的指令参数还有可能是其他的几种形式。

如果请求Request没有Host的头部,那么如果想要匹配,可以用空字符串:

server {
    listen      80;
    server_name  example.org  www.example.org  "";
    ...
}
登录后复制


另外,如果在server上下文中,没有定义 server_name,那么nginx使用空字符串作为虚拟机名称。

如果使用IP而不是域名来发起请求,那么Host请求头就是一个IP,此时server_name也可以写成一个IP:

server {
    listen      80;
    server_name  example.org
                www.example.org
                ""
                192.168.1.1
                ;
    ...
}
登录后复制


"_"可以用来匹配所有的域名

server {
    listen      80  default_server;
    server_name  _;
    return      444;
}
登录后复制

其他的字符,"-"和"!@#"也是可以的。注意,匹配所有域名的不能是"*"


最佳实践

我们知道nginx是一个款高性能的web服务器,其设计充满了许多优化的技巧。在使用的时候也不例外,如果我们能对nginx的设计原理有一些了解,我们在配置时就能很好的利用这些设计,从而使得nginx的效率达到最大化。

前面提到,server_name的指令参数匹配有一定的匹配顺序,即最先匹配精确域名形式,然后匹配以通配符*开始的域名,其次匹配以通配符*结束的域名,最后是匹配正则形式。如果前面匹配到了,就会终止继续匹配。

从原理上说,这是因为,nginx会为每个监听的port分别维护精确域名,前向通配符和后项通配符的Hash表。Hash表能在nginx启动的配置阶段得到创建和优化。精确域名的Hash表首先被搜寻,如果找不到,前向通配Hash表会被接着被搜寻,如果也没有找到,那么后向通配Hash表会被搜寻。搜寻通配Hash表要比精确域名Hash表要慢,因为其是按照域名的部分来做搜寻的(比如,*.example.com,会搜寻example和com部分)。

值得注意的是:".example.org"被存在通配Hash表里面,并没有存在精确Hash表里面,因此匹配它是较慢的。

如果以上两种方式都还没有匹配上,那么最后轮到正则形式的指令上场了。正则形式的域名是按照先后顺序一个一个的去匹配的,没有存入任何Hash表,匹配到正确的就结束,因此,这是最慢的形式,没有任何“技巧”可言。

因此,最好的配置方式就是,尽可能使用精确域名,其次是通配符形式的,最后是正则形式。即便是正则形式域名,也要根据实际需要将用的最多的域名尽量前置。这样方可使得nginx的性能达到最大化。

例如:

server {
    listen      80;
    server_name  example.org  www.example.org  *.example.org;
    ...
}
登录后复制

这种方式要优于:

server {
    listen      80;
    server_name  .example.org;
    ...
}
登录后复制

长域名,多域名的情况

在某些情况下,域名会非常的长,nginx不会允许其无限长,默认最大为32。在http上下文中,你可以通过server_names_hash_bucket_size指令来设置,可选参数有32,64(2的N次方)等

例如,如果域名被定义为:"too.long.server.name.example.org",超过32字符,那么会报错:

could not build the server_names_hash,

you should increase server_names_hash_bucket_size: 32

解决方式:

http {
    server_names_hash_bucket_size  64;
    ...
登录后复制

在另一些情况下,server_name配置的域名又很多,nginx同样可能报错:
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的值(例如将2^N调整到2^(N+1))

http {
    server_names_hash_max_size:600
    server_names_hash_bucket_size 32;
    ...
登录后复制

如果一个域名是某个监听端口下的唯一域名,那么nginx就不会建立Hash匹配表,也不会有上面介绍的那些匹配流程,然而,如果这个唯一的域名是一个捕获组正则表达式,那么nginx还是去尝试去解析正则表达式以提取这个字段。

相关推荐:

php虚拟服务器主机

以上就是Nginx虚拟服务器域名配置方法的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
相关标签:
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
豆包 AI 助手文章总结
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号