| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> Nginx系列之请求处理的11个阶段(上) -> 正文阅读 |
|
[系统运维]Nginx系列之请求处理的11个阶段(上) |
http模块是Nginx的重要模块,此篇博客将围绕Nginx处理请求时的11个阶段展开,并通过实际例子来演示不同阶段引入的module的作用。下图是不同阶段涉及的module说明。下面将依次介绍实际的模块作用。 ?下图是处理请求的11个阶段中,不同模块执行顺序,同一阶段中如果有多个模块,会按下图顺序执行不同模块。另外,还可以在编译后的objs目录下查看ngx_module.c文件,里面存放的模块顺序与模块的执行顺序刚好相反。例如limit_req先于limit_conn执行,在ngx_module.c文件中,从上往下看,先是limit_conn,然后是limit_req.大部分场景下会按如下的模块顺序执行,但也有例外,比如access模块的satisfy指令,当设置satisfy any时,access模块执行后,不再执行auth_basic和auth_request模块,而是跳到try_files模块执行指令。下图中灰色的三个模块(rewrite,find_config,rewrite) 属于nginx框架执行部分,第三方模块无法在这里进行自定义的实现。 接下来就按照模块执行顺序通过实际例子介绍每个模块的主要作用。 ?realip模块:当本机的nginx处于一个反向代理的下游时,获取真实的客户端IP地址 如上图所示,假设用户访问Nginx服务,先经过家里的路由器分配的内部IP地址,再经过运营商的ADSL,也就是真实的一个公网地址,到达CDN,再经过某个反向代理服务,最终才访问到Nginx。在建立连接时,HTTP的头部会有X-Forward-For字段和X-Real-IP字段,这两个字端中会存放经历过的发送请求的服务的IP地址信息和真实的客户端IP地址信息。例如经过CDN往下发送请求时,CDN在请求中就会添加X-Forward-For字段和X-Real-IP字段,达到某反向代理服务器时会再次修改这两个字端的值,需要注意的是:X-Real-IP只能有一个值,而X-Forward-For值是累加的过程。当到达Nginx服务时,如果在没有引入realip模块的情况下,获取$remote_addr,读取到的信息是上一个发送请求的服务地址,也就是2.2.2.2,而实际真正想获取的客户的公网IP是115.204.33.1,获取到IP后就可以进行限流等配置。在这种情况下如何获取真实的客户端公网IP呢?答案是引入realip模块,默认情况下编译nginx不会有此模块,需要通过--with-xx命令添加该模块。引入realip模块后,$remote_addr字段的值会被写成在传递过程中的X-Forward-For的值,而原来的$remote_addr的值,如果要获取,可以通过$realip_remote_addr获取。下面是一段关于realip的配置,可以通过include命令引入到nginx.conf文件中。
当上述配置生效后,如果执行命令:“curl -H 'X-Forwarded-For: 1.1.1.1,10.206.21.246' localhost",此时打印出来的$remote_addr值是10.206.21.246,如果开启real_ip_recursive,那么打印出来的值是1.1.1.1。也就是说,当关闭real_ip_recursive时,服务会取X-Forwarded-For中的最后一个IP地址作为客户端真实地址,当开启real_ip_recursive时,服务会取X-Forwarded-For中的值,如果IP地址等于设置的set_real_ip_from值,会跳过,直到找到一个不等于设置的real_ip_from的值时,将此IP地址作为客户端地址。可以这样理解,当客户端发送请求时,会经过中间哪些服务才达到Nginx,团队是知道的,需要把这些中间服务的IP设置为real_ip_from,这样当客户端发送请求时,就能获取到真正的客户端IP信息。上面还提到header中会通过X-Real-IP传递真实客户端IP的信息,为什么不直接读取X-Real-IP的值呢?因为X-Real-IP是Nginx独有的,不是RFC规范,所以与client间交互时,如果还有其他非Nginx软件实现的代理,将取不到X-Real-IP头部。 rewrite模块下的return和error_page指令 在处理请求的11个阶段中,当return指令生效后,后续的指令都不会再生效。左边是return不同状态码的含义说明,右边是error_page返回不同的状态码,及跳转的页面或者地址配置方式。 ? 下面通过实际例子来演示开启不同配置的区别,结果如下图所示:假设注释掉location中的return和server中的return指令,访问“curl http://taoli.test.pub:8070/test.txt”,因为配置了root html/,所以当curl的时候,会从nginx的html文件夹下查找是否存在test.txt文件,实际目录中不存在该文件,所以会执行error_page 404的结果。此时,将location中的return注释取消掉,再次访问,会返回“find nothing”的信息,说明同时配置error_page和return指令时,会优先执行return指令。此时再把server中的return指令的注释也取消掉,再次访问服务,会返回405的信息,因为server和location中的return指令都属于rewrite阶段,server模块的指令会先于location中的指令执行。故返回405. 另外,需要注意,error_page最后接的是uri地址而不是文件路径。假如设置了server_name是 taoli.test;? ?root /var/www;? error_page 404 /404.html; 当出现404时会跳转到 http://taoli.test/404.html。如果写成 error_page 404 404.html,当访问 http://taoli.test/sss/ddd 出现404时,他会跳到 http://taoli.test/sss/ddd/404.html。 rewrite模块下的rewrite指令 rewrite后面配置期望替换的url,替换的url中可以使用正则表达式,变量等。替换后的url后面还可以配置不同的flag来进行不同的处理,flag和处理逻辑规则如下 下面通过实际例子来演示不同rewrite后,实际访问到的页面。假设在nginx的html目录下有三个目录first,second,third,三个目录下分别存放了txt文件,location中配置如下所示 当注释掉break的那一条指令时,执行“curl http://taoli.test.pub:8060/first/3.txt”返回的是 “this is 3.txt”,因为当访问/first时,被重定向到了/second,而/second下面又重定向到了/third下面,所以最终返回3.txt。当访问"curl http://taoli.test.pub:8060/second/3.txt" ,同理。当取消掉break这条指令的注释后,访问“curl http://taoli.test.pub:8060/first/3.txt”返回了"second",因为当/first重定向到/second时有break,取消了当前的重定向规则,所以执行了/second里面的return指令。 rewrite模块下的If指令 ?如上图所示,当写入if指令时,if中的判断条件可以有变量,正则表达式,等于符号等。这里总结了常用的一些if表达式,如下所示
Find_config阶段的Location指令块 Location指令块在进行匹配时,主要分为前缀匹配和正则表达式匹配,在进行这两类匹配时遵循下面的规则。 前缀匹配 当同时多种规则符合时,最终会采用哪一条规则呢?实际Nginx在进行匹配时执行顺序如下所示: 首先会遍历所有的Location下的前缀匹配,如果命中精确匹配,那么采用精确匹配的location,如果未命中精确匹配,命中了^~后的字符串(即访问路径的字符串值等于^~后的字符串),则采用^~的location。如果都未命中,则进行正则表达式匹配,命中,则采用正则表达式的location,如果有多个正则表达式,按在location中的配置顺序,排在前面的生效。如果都没有命中,则记录最长匹配的前缀字符串locaiton,最长匹配指location中的字符串能匹配到的长度最长的那一条。接下来通过实际例子来看看。 假设curl命令访问左边的地址,左边是配置文件中的location指令块的配置,执行每一条命令后,最终会返回什么结果呢?执行结果如下图所示。这里来分析下为什么会得到下面的实验结果,从一条命令开始。 当访问/Test1时,精确匹配到了上图右边的最后一条规则,所以返回"exact match" 当访问/Test1/时,实际匹配了上图右边的第一、二、三、五条规则,匹配到了第三条的字符串,且第三条规则是^~开头,所以采用第三条规则的location,返回"stop regular expressions match" 当访问/Test1/Test2时,匹配到了第一、二、四、五条规则,因为第二条属于正则表达式,所以采用了第二条的locaiton,返回"longest regular expressions match" 当访问/Test1/Test2/时,匹配到了第四、五条规则,第四条规则的前缀更长,所以返回"longest prefix string match" 以上就是对Location匹配的介绍,下一篇博客中会接着继续介绍处理请求的11个阶段所涉及的模块。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/28 19:10:53- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |