时间:2021-01-21 10:48:54 | 栏目:Nginx | 点击:次
nginx的配置指令的作用域可以分为 main,server,location这3个种,实际上这3者不是依次包含的关系,而是相互独立的关系,比如一个只具有main级别作用域的指令,是不能写在某个server或者location内的,模块的某个指令可以同时具有main,server,location这3种作用域,另外每个模块有 main,srv,loc这3个级别的配置,一个模块的main级别的配置对所有的server和location都是共享的,srv级别的配置对所有 location都是共享的,location只有自己独立的loc级别的配置,这就是为什么一个模块的srv和loc级别的配置需要merge,而 main级别的配置不需要merge的原因。这里看起来有点绕,区分一下main,server,location分别作为一种作用域级别和一个主体,类似于形容词和名字的区别,nginx的配置关系还是不难理解的。
一般来说一个请求url过来,nginx会将它解析到某一个location来处理。这个解析的过程实际上根据location的配置基本可以分为字符串匹配和正则表达式匹配这2种。对于location的组织方式,最简单的就是直接将它们保存为一个链表,解析url的时候一个一个遍历即可找到相应location,但是这样效率太低,对像nginx这种高性能的服务器来说是完全不可取的,nginx将字符串匹配的location组织成了一个三叉的字符串排序树,而且建立的时候也考虑了树的平衡性。文章后面我讲详细介绍源码的实现。
首先我来大概的介绍一下location的种类和匹配规则,以nginx wiki(http://wiki.nginx.org/HttpCoreModule#location)的例子做说明:
location 优先级官方文档
=前缀的指令严格匹配这个查询。如果找到,停止搜索。
所有剩下的常规字符串,最长的匹配。如果这个匹配使用^〜前缀,搜索停止。
正则表达式,在配置文件中定义的顺序。
如果第3条规则产生匹配的话,结果被使用。否则,如同从第2条规则被使用。
例如
location = / { # 只匹配"/". [ configuration A ] } location / { # 匹配任何请求,因为所有请求都是以"/"开始 # 但是更长字符匹配或者正则表达式匹配会优先匹配 [ configuration B ] } location ^~ /images/ { # 匹配任何以 /images/ 开始的请求,并停止匹配 其它location [ configuration C ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配以 gif, jpg, or jpeg结尾的请求. # 但是所有 /images/ 目录的请求将由 [Configuration C]处理. [ configuration D ] }
可以看到上面的例子中有5种不同类型的location,其中第4个带 “~” 号前缀的为需要正则匹配的location,nginx在进行url解析时对这5种不同类型的location具有不同的优先级规则,大致的规则如下:
1,字符串精确匹配到一个带 “=” 号前缀的location,则停止,且使用这个location的配置;
2,字符串匹配剩下的非正则和非特殊location,如果匹配到某个带 "^~" 前缀的location,则停止;
3,正则匹配,匹配顺序为location在配置文件中出现的顺序。如果匹配到某个正则location,则停止,并使用这个location的配置;否则,使用步骤2中得到的具有最大字符串匹配的location配置。
例如,对下面的请求有:
1, / -> 精确匹配到第1个location,匹配停止,使用configuration A
2,/some/other/url -> 首先前缀部分字符串匹配到了第2个location,然后进行正则匹配,显然没有匹配上,则使用第2个location的配置configurationB
3,/images /1.jpg -> 首先前缀部分字符串匹配到了第2个location,但是接着对第3个location也前缀匹配上了,而且这时已经是配置文件里面对这个url的最大字符串匹配了,并且location带有 "^~" 前缀,则不再进行正则匹配,最终使用configuration C
4,/some/other/path/to/1.jpg -> 首先前缀部分同样字符串匹配到了第2个location,然后进行正则匹配,这时正则匹配成功,则使用congifuration D
请求URI例子:
/ -> 符合configuration A /documents/document.html -> 符合configuration B /images/1.gif -> 符合configuration C /documents/1.jpg ->符合 configuration D @location 例子 error_page 404 = @fetch; location @fetch( proxy_pass http://fetch; )
location匹配命令
location 匹配的优先级(与location在配置文件中的顺序无关)
= 精确匹配会第一个被处理。如果发现精确匹配,nginx停止搜索其他匹配。
普通字符匹配,正则表达式规则和长的块规则将被优先和查询匹配,也就是说如果该项匹配还需去看有没有正则表达式匹配和更长的匹配。
^~ 则只匹配该规则,nginx停止搜索其他匹配,否则nginx会继续处理其他location指令。
最后匹配理带有"~"和"~*"的指令,如果找到相应的匹配,则nginx停止搜索其他匹配;当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。