返回顶部
首页 > 资讯 > 服务器 >讨论nginx location 顺序问题
  • 650
分享到

讨论nginx location 顺序问题

2024-04-02 19:04:59 650人浏览 泡泡鱼
摘要

目录一、location 是什么二、location 的选项有哪些?三、location 的匹配规则前缀字符串正则表达式总结四、location 的应用规则理论篇实践篇精准匹配优先级

网上有很多讨论 Nginx location 顺序的话题,得到的结论也基本一致,总结为:

  • 精准匹配 =
  • 前缀匹配 ^~
  • 正则匹配 ~~*
  • 不带修饰符的前缀匹配

在很长的一段时间里,我对上述的结论也一直深信不疑,甚至还将这个结论分享给其他小伙伴,直到在有一次配置时发现,请求 uri 明明是符合了前缀匹配 ^~ 规则,但 nginx 却没有使用,这让我对上述结论产生了疑惑。后续通过调研、实践后发现,上述结论可以说对,但也不对,是不是更疑惑了?没关系,看完这篇文章你就知道我为什么会这样说了。

本篇文章会从以下五个方面来介绍 location 顺序问题

  • location 是什么
  • location 的选项有哪些
  • location 的匹配规则是什么
  • location 的应用规则是什么
  • 总结

话不多说,我们直接进入正题。

一、location 是什么

location 翻译成中文就是定位,已经描述的比较清晰了,因为它的作用就是根据请求 uri 定位到某一个规则块,然后在由该规则块决定怎么处理用户的请求。

location 模块看起来挺简单的,但真要自己写,有时候就会觉得无从下手,我应该用 location /imageslocation ^~ /images 还是 location ~ /images 呢?我应该帮这个location 规则放在什么位置呢?将规则放在最前面会影响已有的配置吗?....上面说的问题,相信大部分同学都遇到过,想要彻底解决,就必须要了解 location 的处理逻辑,当然这也是本篇文章的目的所在。

二、location 的选项有哪些?

location [ = | ~ | ~* | ^~ ] uri { ... }

按照匹配模式进行区分,location 后可以放置两种类型的匹配规则,分别是前缀字符串(prefix string)和正则表达式(regular expression)。其中前缀字符串包括 =^~ 以及不设置(也就是空串),而正则表达式只有 ~~*。(这五种选项是经常看到的,还有一种不常用的 location @name { ... } ,并不在今天的讨论范围)

三、location 的匹配规则

只有请求 uri 满足 location 的规则,才有可能被应用,而对于不同的匹配模式,location 的匹配规则也是不同的

前缀字符串

顾名思义,它表示从请求 uri 的开头开始进行匹配,如果用 javascript 来描述的话,当 uri.indexOf(locationRule.uri) === 0 时表示满足匹配规则,其中 uri 表示请求路径,而 locationRule.uri 表示 location 设置的规则。

其中 = 选项比较特殊,它又叫做精准匹配,只有匹配规则与请求 uri 完全相等时才表示满足条件,即只有当 uri === locationRule.uri 时才表示匹配成功。

正则表达式

其实就是通过正则匹配来验证是否满足规则,nginx 使用的是 Perl 兼容正则表达式 (PCRE),网上可以找到很多验证正则表达式的站点,这里就不再展开了。但要注意,为了方便配置,nginx 进行了一些非标准的优化,例如,不必像在标准正则表达式中那样转义 URL 中的正斜杠(/)等等。

而对于 ~~* 唯一的区别就是:~ 区分大小写,而 ~* 不区分大小写。

总结

下面,我们对 location 的选项进行一个简单的总结

选项匹配规则示例
=精准匹配location = /test {...}
^~从请求 uri 的开头进行匹配location ^~ /test {...}
[空串]从请求 uri 的开头进行匹配location /test {...}
~区分大小写的正则匹配location ~ /test {...}
~*不区分大小写的正则匹配location ~* /test {...}

四、location 的应用规则

理论篇

在了解完匹配规则后,我们来看下 nginx 是如何应用这些规则的,这就要说到 location 的顺序问题了。

下面是根据实践以文档总结出来的 location 应用规则的逻辑:

  • server 块中的 location 按照匹配模式分成两个列表,分别为前缀字符串规则列表和正则匹配规则列表。
  • 首先遍历前缀字符串规则列表,当满足匹配的规则是精准匹配时(即匹配选项是 =),直接应用该规则,结束流程;否则找到匹配规则最长的那条记录(记作 maxLenthStringPrefixRule),继续执行逻辑3;
  • 如果 maxLenthStringPrefixRule 存在且匹配选项是 ^~ ,应用该规则,结束流程;否则,执行逻辑4;
  • 遍历正则匹配规则列表,如果满足匹配规则,则直接应用,流程结束;如果直到循环结束后依然没有满足规则的 location,则执行逻辑5;
  • 如果 maxLenthStringPrefixRule 存在,则应用该规则,流程结束;如果没有则返回 404,同样结束流程。

如果上述描述看着很难理解,可以尝试看下面的伪代码。

// 字符串匹配的规则集合,按照在 .conf 文件中的顺序放置到该集合中
const stringPrefixRuleList = [...]
// 正则匹配的规则集合,按照在 .conf 文件中的顺序放置到该集合中
const regularExpressionRuleList = [...]
// 用于存放最长字符串匹配的规则
let maxLenthStringPrefixRule;
// 遍历字符串匹配的规则集合
for (let stringPrefixRule of stringPrefixRuleList) {
    // 符合匹配规则
    if (stringPrefixRule.isMatched()) {
        // 匹配选项是精准匹配
        if (stringPrefixRule.option === '=') {
            // 应用该规则,结束流程
            applyRule(stringPrefixRule);
            return;
        }
        // 将最长匹配规则记录下来,留到后面使用
        if (!maxLenthStringPrefixRule 
            || stringPrefixRule.uri.length > maxLenthStringPrefixRule.uri.length) {
            maxLenthStringPrefixRule = stringPrefixRule
        }
    }
}
// 如果最长匹配规则的选项是 ^~, 则应用该规则,流程结束
if (maxLenthStringPrefixRule && maxLenthStringPrefixRule.option === '^~') {
    applyRule(maxLenthStringPrefixRule);
    return;
}
// 遍历正则匹配规则集合
for (let regularExpressionRule of regularExpressionRuleList) {
    // 如果有规则匹配上,则直接应用,流程结束
    if (regularExpressionRule.isMatched()) {
        applyRule(regularExpressionRule);
        return;
    }
}
// 如果最长字符串匹配的规则存在,则应用该规则
if (maxLenthStringPrefixRule) {
    applyRule(maxLenthStringPrefixRule);
    return;
}
// 404,规则未找到
throw new Error(404)

由此,我们可以得到几个结论:

  • 命中 = 匹配规则后会终止搜索,并直接使用该规则。所以,如果某个请求 url 频繁发生,例如 /,我们可以在 nginx.conf 中添加 location = / 规则,这会加速这些请求的处理速度,因为在命中规则后会终止搜索。
  • ^~ 和空串的前缀匹配,区别在于,如果命中 ^~ 的规则,并且是最长前缀匹配,就会终止搜索正则匹配规则列表。
  • 除了命中精准匹配外,前缀字符串匹配列表都会被遍历一遍,并且找到最长匹配的那条 location 规则,所以前缀字符串匹配和在文件中的位置无关,但是和匹配长度有关
  • 由于正则匹配的时间、资源消耗较多,所以 nginx 在对 location 规则进行正则匹配时,命中一个就直接使用了,所以正则匹配和 location 规则在文件中的位置有关

实践篇

从上面的理论篇中,大家应该能大致了解到 nginx 是如何命中 location 规则的,为了加深大家记忆,同时也为了能佐证理论是对的,我们来一些实践吧。

我们的模板是这样的,后面所有的实践内容,都是放到两个 rule section 之间。

server {
    listen	9001;
    location / {
        default_type text/html;
        return 200 'hello world';
    }
    # ===== rule section ======
    # ===== rule section ======

精准匹配优先级最高

location /test {
    default_type text/html;
    return 200 '/test';
}

location ~ /test {
   default_type text/html;
   return 200 '~ /test';
}

location = /test {
   default_type text/html;
   return 200 '= /test';
}

我们在 nginx.conf 放置了 /test~ /test= /test 三个 location 规则,随后在浏览器输入 localhost:9001/test,发现输出内容是 = /test,符合我们的预期,= 选项的优先级最高。

正则匹配和顺序有关

location ~ /test {
   default_type text/html;
   return 200 '~ /test';
}

location ~ /testdemo';
}

随后我们将 rule section 区块替换成 ~ /test~ /testdemo 规则,但是由于 ~ /test 在文件中位置靠前,所以优先被命中,理论上应该会输出 ~ /test,校验后发现,确实是这样。

正则、^~前缀匹配、空前缀匹配混搭

location ^~ /test {
   default_type text/html;
   return 200 '^~ /test';
}
location /test/more/andmore {
   default_type text/html;
   return 200 '/test/more/andmore';
}
location ~ /test {
   default_type text/html;
   return 200 '~ /test';
}

将 section rule 区域替换成上述内容,然后在浏览器中输入 localhost:9001/test/more/andmore,猜猜会发生什么?

我们来一起分析下:

  • 没有精准匹配的规则
  • 找到最长的前缀字符串匹配规则是 /test/more/andmore,它不是 ^~ 选项,所以会遍历正则匹配规则
  • 发现 ~ /test 满足匹配规则,直接应用该规则,所以会输出 location ~ /test 规则块的内容,也就是 ~ /test

我们再来试一下,在浏览器输入 localhost:9001/test/more,会显示什么呢?

  • 没有精准匹配规则
  • 最长前缀字符串匹配规则是 ^~ /test,是 ^~ 选项,所以不用遍历正则匹配规则列表,所以页面会显示 ^~ /test

通过校验后发现,上述分析的结果和实际显示结果是一样的。

上面几个实践都比较简单,大家也可以尝试各种组合,然后按照上面的分析步骤来检验下自己是不是真的理解了 location

五、总结

看完上面的介绍,相信大家对 location 规则的处理逻辑都有一定的了解,也应该明白为什么在文章开头说曾经看到的结论对、也不对了。

如果要用对 location 顺序进行总结的话,可以在原有的基础上适当的进行一些扩展:

  • 精准匹配 =
  • 前缀匹配 ^~如果该前缀匹配是最长前缀匹配规则,则应用
  • 正则匹配 ~~*和该规则在文件中的顺序有关,执行顺序从上到下
  • 不带修饰符的前缀匹配,和匹配规则的长度有关,只会应用最长的匹配规则,与在文件中的顺序无关

参考链接:nginx.org/en/docs/htt…

到此这篇关于nginx location 顺序问题的文章就介绍到这了,更多相关nginx location 顺序内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 讨论nginx location 顺序问题

本文链接: https://lsjlt.com/news/150018.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 讨论nginx location 顺序问题
    目录一、location 是什么二、location 的选项有哪些?三、location 的匹配规则前缀字符串正则表达式总结四、location 的应用规则理论篇实践篇精准匹配优先级...
    99+
    2024-04-02
  • 讨论Oracle 中sql语句的执行顺序
    查询语句的执行顺序:select ename as name from scott.emp emp where emp.job=' CLERK' order by name;sele...
    99+
    2024-04-02
  • db_file_name_convert顺序问题
    duplicate时如果远程的一个目录空间不够,可以把文件拆分到两个目录,使用db_file_name_convert即可 db_file_name_convert不是对目录名称进行转换,而是对文件名称进行...
    99+
    2024-04-02
  • Nginx location 和 proxy_pass路径配置问题小结
    目录一、Nginx location 基本配置1.1、Nginx 配置文件1.2 、Python 脚本二、测试2.1、测试 location2.2、测试 location2.3、测试...
    99+
    2024-04-02
  • Nginx的location的常见规则优先级问题
    目录一、Location / 匹配二、Location = / 匹配locaiton有四种类型的匹配规则,分别为完全匹配(=)、前缀普通匹配(^~)、正则表达式匹配(~或者~*)、普...
    99+
    2024-04-02
  • 讨论PHP除以10000的精度问题
    PHP是一种广泛使用的服务器端编程语言,它可以嵌入HTML中,也可以用于开发Web应用程序、命令行脚本和桌面应用程序。在PHP中,我们常常需要进行数字计算,而这些计算可能会遇到精度问题。本文将介绍PHP除以10000的精度问题,并提供解决方...
    99+
    2023-05-14
    精度 php
  • 从顺序随机I/O原理来讨论MYSQL MRR NLJ BNL BKA
    从顺序随机I/O原理来讨论MYSQL MRR NLJ BNL BKA 本文只讨论innodb存储引擎,并且有部分观点为作者观点,如果有误请指出。 一、机械磁盘原理     机械盘由...
    99+
    2024-04-02
  • JAVA - fastjson 中 JSONObject 的顺序问题
    目录 1. JSONObject  存在的默认排序问题一 1.1. 解决方案一 1.2. 解决方案二 2. JSONObject  存在的默认排序问题二 2.1. 解决方案一 2.2. 解决方案二 在使用 fastjson 中的 JSON...
    99+
    2023-09-11
    java 开发语言 数据结构
  • 讨论Golang错误重试的一些问题和技巧
    在使用Golang编写应用程序的过程中,错误处理是必不可少的一部分。然而,在面临一些不可避免的错误时,我们可能需要尝试多次进行操作以达到成功。这就是所谓的错误重试。在本文中,我们将讨论有关Golang错误重试的一些问题和技巧。什么是错误重试...
    99+
    2023-05-14
  • C++中数据结构问题及解决方案的讨论
    C++中数据结构问题及解决方案的讨论导语:在C++编程中,数据结构是一个重要的概念,它能够帮助我们以一种有组织的方式存储和管理数据。然而,当面临复杂的问题时,我们可能会遇到一些困难,如何合理地选择和使用数据结构成为一个关键的问题。本文将介绍...
    99+
    2023-10-22
    链表 例如数组 队列等。
  • C++中数据结构问题和解决方案的讨论
    C++中数据结构问题和解决方案的讨论数据结构是计算机科学中非常重要的概念之一,它是存储和组织数据的方式和方法。在C++编程中,我们经常会遇到各种各样的数据结构问题,比如如何高效地存储和操作数据,如何实现各种常见数据结构等等。本文将探讨C++...
    99+
    2023-10-22
    数据结构: 数据 解决方案: 解决 讨论: 讨论
  • 讨论php在捕获异常方面存在一些问题
    PHP是一种开源的脚本语言,被广泛用于开发Web应用程序。PHP具有灵活的语法、易于学习和使用以及强大的扩展性、高效性等特点,深受开发者的青睐。但是,PHP也存在一些问题,在开发过程中需要注意。其中之一就是PHP在捕获异常方面存在一些问题。...
    99+
    2023-05-14
    捕获异常 php
  • MySQL读取my.cnf的顺序问题详情
    目录MySQL读取my.cnf的顺序一、mysql.server启动方式二、mysqld_safe启动方式三、关于mysqld和my_print_defaults读取my.cnf顺序...
    99+
    2024-04-02
  • rabbitmq消息顺序问题怎么解决
    要解决 RabbitMQ 消息顺序问题,可以考虑以下几种方法:1. 使用单个队列:将需要保持顺序的消息发送到同一个队列中,这样 Ra...
    99+
    2023-10-12
    rabbitmq
  • C++中多态性实现问题及解决方法的讨论
    C++中多态性实现问题及解决方法的讨论多态性是C++语言中一项非常重要的特性,它使得一个类的对象可以根据其具体类型表现出不同的行为。然而,在实际的应用中,我们有时会遇到一些问题,特别是在多继承和虚析构函数的使用场景下。一、多态性的实现在C+...
    99+
    2023-10-22
    多态性 (Polymorphism) C++编程 (C++ programming) 实现问题 (Implementat
  • 详解JavaScript Alert函数执行顺序问题
    目录问题分析解决替换 Alert() 函数setTimeOut函数小结问题 前几天使用 JavaScript 写 HTML 页面时遇到了一个奇怪的问题: 我想实现的功能是通过 con...
    99+
    2024-04-02
  • 浅谈@Value和@Bean的执行顺序问题
    问题描述 使用@Autowired处理多个同种类型的bean,出现@Value和@Bean的执行顺序问题。 首先使用扫描包+注解的方式注册User类型的不同bean,分别是user、...
    99+
    2024-04-02
  • 详解JS对象遍历的顺序问题
    可能有些同学听过在 JavaScript 中遍历对象顺序不固定的这一说法。事实上,这个说法不是特别准确。 对待遍历顺序,对象有一套自己既定的规则,在此规则下呢,对象的遍历顺序会受插...
    99+
    2024-04-02
  • 讨论在线教室 iOS 端声音问题综合解决方案
    目录背景介绍AVAudioSessionAVAudioSessionMode AVAudioSessionOptions通话音量与媒体音量行业现状听不见 RTC 声音媒体声...
    99+
    2022-05-31
    IOS 在线教室 声音
  • 解决json字符串序列化后的顺序问题
    1、应用场景: 如果项目中用到json字符串转为jsonObject的需求,并且,需要保证字符串的顺序转之前和转成jsonObject之后输出的结果完全一致。可能有点绕口,下面举一个...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作