nginx烂笔头——Server names

说明:“Nginx烂笔头”系列Blog是自己对Nginx官方文档的的翻译,用作阅读笔记便于日后查阅的成分居多,无关重要内容会删减,也可能会加入自己的理解。囿于个人水平,一些专业的名称翻译不会太准确,推荐查看Nginx官网原始文档。翻译内容如果有错误,欢迎指正。

本文翻译自Nginx官网Server names网页文档。

摘要

本文主要讲述了server指令块中server_name指令的使用事项,主要为server_name指令的精确命名、通配符命名、正则表达式命名和其他命名方法。

一、server_name指令命名方法总览

服务名称是使用server_name指令定义的并决定了一个请求使用哪一个服务块来处理。可以参考How nginx processes a request。服务名可以使用一个确切的、通配符或者正则表达式来命名。

#确切地指定一个名称
server {
    listen       80;
    server_name  example.org  www.example.org;
    ...
}

#通配符命名
server {
    listen       80;
    server_name  *.example.org;
    ...
}

#通配符命名2
server {
    listen       80;
    server_name  mail.*;
    ...
}

#正则表达式命名
server {
    listen       80;
    server_name  ~^(?<user>.+)\.example\.net$;
    ...
}

1.1 搜索规则

当nginx通过名称来搜索虚拟服务时,如果一个名称匹配到多个指定的服务块,例如,同时匹配上了通配符和正则表达式的,那nginx会按照下面优先级来选择最先匹配到的server块来处理这个请求

1. 准确的名称
2. 以号开始最长的通配符命名
3. 以
号结束最长的通配符命名
4. 第一个匹配到的正则表达式命名(按照在配置文件出现的先后顺序)

二、通配符命名

一个通配符名称可以在开始或结束包含号,也可以在“.”号之间。名称www.*.example.org```和```w*.example.org都是正确的命名 。然而,这些名称也可以使用正则表达式来命名,例如,~^www\..+\.example\.org$~^w.*\.example\.org$。一个号可以同时匹配上server name以“.”号分割的不同部分。*.example.org可以同时匹配上www.example.orgwww.sub.example.org这两个服务名称。

A special wildcard name in the form “.example.org” can be used to match both the exact name “example.org” and the wildcard name “*.example.org”.

三、正则表达式命名

3.1 使用规则

nginx使用的正则表达式和Perl语言使的(PCRE)是兼容的,server_name的参数必须以~开头:

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

否则,nginx会把参数视作一个准确的名称,如果表达式包含一个*号,则会被视作一个通配符命名方式。不要忘记^$符号。他们在语法上不是必须的,但是在(nginx)逻辑上是必须的。同时注意,域名的“."符号需要使用反斜线进行转义。表达式里面如果有“{”和“}”需要用括号扩起来:

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

否则,nginx会启动失败并抛出下面的错误信息

directive “server_name” is not terminated by “;” in …

3.2 表达式变量

正则表达式中的字段可以被捕获成一个变量,在接下来可以使用:

server {
    server_name   ~^(www\.)?(?<domain>.+)$;

    location / {
        root   /sites/$domain;
    }
}

PCRE库使在不同版本对变量捕获的语法支持:

  • ? 兼容Perl 5.10语法,从PCRE-7.0开始支持
  • ?’name’ 兼容Perl5.10语法,从PCRE-7.0开始支持
  • ?P 兼容Pyton语法,从PCRE-4.0开始支持

如果ngins启动失败,并出现下面的错误信息:

pcre_compile() failed: unrecognized character after (?< in …

这说明PCRE库版本太旧,应该使用?P 语法。
捕获也可以使用数字的格式:

server {
    server_name   ~^(www\.)?(.+)$;

    location / {
        root   /sites/$2;
    }
}

但是,这种用法应该被限制在简单的例子中使用,比如上面的,因为数值应用容易被重写覆盖。

其他命名方式

有一些其他的命名方式被特殊对待。

在一个不是默认server块指令中需要处理不带“Host”请求头的请求,需要加上空名称:

server {
    listen       80;
    server_name  example.org  www.example.org  "";
    ...
}

如果server指令块种没有指定server_name指令,nginx回默认用空字符串做server_name。

nginx在0.8.48前都是用机器的主机名作为服务名。

如果服务名被定义为"$hostname"(0.9.4),就回使用机器的主机名。

如果请求是使用ip的也可以配置在服务名种,nginx也会处理:

server {
    listen       80;
    server_name  example.org
                 www.example.org
                 ""
                 192.168.1.1
                 ;
    ...
 }

在下面的例子中会处理所有host的请求,你可以看到有一个“_”字符串:

server {
    listen       80  default_server;
    server_name  _;
    return       444;
}

名称没有特别之处,都是不合法的host之一。其他类似的不合法字符,如:“!@#”也可以使用。

nginx在0.6.25之前都支持特殊名称“*”,通常会被错误地认为是用来处理所有host请求地特殊名字。使用“*”从来不会起到处理所有host地作用,或者类似一个通配符名称。相反地,它提供了server_name_in_redirect指令地功能。现在,“*”已经被弃用,应该使用server_name_in_redirect指令来代替。需要注意的是,使用server_name指令不能配置一个默认的server或者处理所有请求的server。可以查看How nginx processes a request.只能指定默认的host是默认由8080端口来处理的,其他请求都会有80端口处理。

server {
    listen       80;
    listen       8080  default_server;
    server_name  example.net;
    ...
}

server {
    listen       80  default_server;
    listen       8080;
    server_name  example.org;
    ...
}

国际化域名

国际化域名需要在server_name指令中使用ASCII表示:

server {
    listen       80;
    server_name  xn--e1afmkfd.xn--80akhbyknj4f;  # пример.испытание
    ...
}

优化

准确名称,以“*”号开头或结尾的通配符名称被存储在和端口绑定的3个哈希表中。哈希表的大小是可以使用配置文件来优化的,以减少CPU的未命中缓存时间来加快检索。具体可以查看此文档.

三张哈希表的优先顺序是:准确名称哈希表,“*号”开头的哈希表,“*号”结束的哈希表。

搜索通配符名称要比准确的名称慢因为是根据域名不分来检索的。需要注意的是特殊通配符“.example.com"是保存在通配符哈希表中的而不是准确名称哈希表中。

正则表达式会被顺序的匹配,所以是最慢的一个而且无法伸缩。

所以,如果可以最好使用准确的名称。例如:如果最频繁的访问是example.org和www.example.org,最有效率的配置是直接配置:

server {
    listen       80;
    server_name  example.org  www.example.org  *.example.org;
    ...
}

比这样简单的配置要高效:

server {
    listen       80;
    server_name  .example.org;
    ...
}

如果配置了很多server name或者很长的server name,那有必要通过http指令块中的server_name_hash_max_sizeserver_names_hash_bucket_size指令来调整哈希表的大小。server_names_hash_bucket_size默认值是32或者64,取决于CPU的缓存页大小。如果值是32,但是server name过长,会报以下的错误:

could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32

此时,需要修改server_names_hash_bucket_size,数值需为2的N次幂:

http {
    server_names_hash_bucket_size  64;
    ...
    }

如果过多server name会报下面的异常:

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_name_hash_max_size的大小。

如果server只监听了一个端口,nginx完全就不会匹配server name了,也就不会创建三张哈希表。有个例外就是,当server name是正则表达式的时候还是会去匹配server name了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值