乔治于2020年04月04日 nginx 配置文件 优先级 优化 location

在反向代理的场景下,nginx用的人很多。在使用nginx的过程中,除了常规的反向代理配置,还经常临时性的要封个请求,加个限速,跳转一下等是常有的事情。这些都和location的配置规则相关。

location语法

location支持5种语法,分别为:

1. location =   /uri {}   #完整字符串匹配,优先级最高,发现匹配就停止
2. location ^~  /uri {}   #字符串前缀匹配,发现匹配就停止。这个不是正则匹配
3. location     /uri {}   #字符串前缀匹配,取最具体的那个匹配(the most specific match),可理解为最长匹配。这里即使是找到了匹配,也会继续执行后面的正则匹配。
4. location ~   /uri {}   #正则匹配,大小写敏感。按在配置文件中定义的顺序执行,发现匹配就停止(The first regular expression to match the query will stop the search))
5. location ~*  /uri {}   #同规则4(~),区别就是正则匹配时大小写不敏感

“发现匹配就停止”的意思是匹配过程终止了,已经得到了匹配结果并提前返回了,不会在执行后面的匹配了。

执行顺序

  • 执行完整字符串匹配。从1)开始搜索,如果1)找到匹配,则停止搜索;

  • 执行字符串前缀匹配。执行2),3),目的是找到最具体的那个匹配。此过程不会停止整个匹配过程,完成后会继续执行正则匹配。唯一的例外是,如果location的操作是^~,只要发现匹配就停止搜索;

  • 执行正则匹配。4),5),按照配置文件中出现的顺序挨个匹配,如果发现匹配则停止搜索;

  • 相同规则内执行顺序是按照规则在配置文件中出现的顺序从上到下顺序执行的。

一句话概括一下就是先执行完整字符串匹配,找到匹配就结束,没有找到匹配,就继续执行前缀和正则匹配,最后就是如果找到正则匹配,就用正则匹配结果,如果没有找到,就用前缀匹配的结果。当然,有一个例外。

匹配结果

根据执行顺序节的解释,我们可以确定匹配结果的优先级是:完整字符串匹配 > ^~前缀匹配 > 正则匹配 > 字符串前缀匹配

location优化建议

根据不同匹配的不同规则,

  • 在确定的情况下优先使用完整字符串匹配(=),

  • 接下来优先使用(^~)。

  • 接下来就是正则匹配的location要合理排序,最常用,访问最多的要排到前面。

  • 最后是少写不带操作符的字符串前缀匹配。也就是location语法中的3.原因是a)这个过程是在正则匹配之前执行的,为了找到最具体的匹配,应该是需要全部执行;b)它的结果优先级没有正则匹配的高,如果后来发现了正则匹配,此过程就没有意义了。

同时应该注意的是正则匹配(4,5)是按照配置文件中出现的顺序挨个匹配,取第一个匹配的结果。如果顺序安排不当,会有覆盖的结果。比如:

location ~ /uri {}           (1)
location ~ /uri/\d{1,}/ {}   (2)

这个配置文件,如果遇到/uri/12345/这个请求的时候,最后的匹配结果是uri <1>,而不是后者 <2>。