一 error_page和proxy_intercept_errors深究
强调: 本文只是基于'状态'码的角度来讨论'error_page'、'proxy_intercept_errors'差异性
题外话: 让别人'定位',一定要保留好'事故现场',尽可能的提供更多的'有用'信息
核心: 本文只讨论'错误状态码'的异常处理
遗留: 关于1xx、2xx、3xx、4xx、5xx'状态码'后续再开'几个小节'进行深入探讨
提醒自己: 不要陷入'开源软件'里面无法出来,站在'更高的维度'思考问题
① 知识铺垫
proxy模块上游出现失败时的容错方案
proxy_intercept_errors指令应用
try_files、internal、error_page指令
上游服务器出问题了,nginx 还能获取到响应吗?
error_page案例
② 问题引入
1) 目的:带着'问题'来学习,效率事倍功半
2) 问题1:$status和$upstream_status的'关联'?
[1]、客户端'显示'的状态码、$status、$upstream_status、后端服务器的'记录'状态码关联
[2]、nginx'特有'定义的状态码:444、497、498、499
[3]、没有'建立'连接nginx会自身填充'(一般涉及5xx报错)'
[4]、后端'回传'了一个nginx'不能识别'的状态码?
3) 问题2:proxy_intercept_errors on 时,error_page 一定会处理吗? --> "优先级"
[1]、不一定,看'条件'
[2]、proxy_next_upstream'默认'不会截胡,但是可以'显示'的配置'部分'状态码
效果:导致拦截了'状态码',使nginx'重新尝试'与上游的另一台服务器'建立链接'
[3]:proxy_next_upstream 能处理'tcp层'、'tls/ssl层'、'应用层(http层)'
[4]:proxy_next_upstream'如果涉及状态码',根据处理阶段,'优先级'比error_page更高
4) 问题3:proxy_next_upstream关于'响应状态码'是针对'$upstream_staus'的吗?
[1]、'不准确',因为'nginx与后端'可能就'没有'建立链接,但是nginx自身'填充'了相应的'数值'
常见: 502、504,'4xx'不常见
5) 问题4:error_page 对默认针对'$status'状态码进行处理
[1]、error_page 默认处理的是nginx自身的一些错误状态码
[2]、但是可以通过proxy_intercept_errors on|off控制'是否处理上游'的'错误'状态码
[3]、error_page常见的几种'处理场景'
1、给一个常规的静态页面'不改变状态码'
2、给一个internal重定向'/或@的形式'
3、'修改'状态码
③ error_page
作用: 是当发生'错误'的时候,nginx通过'状态码'进行'补获',进行'特定'的处理
备注:不一定非得是'发生错误',error_page实际是根据'状态码'进行判断,决定'是否'处理
场景:
[1]、通常是'是否'传递'4xx和5xx'错误信息到'客户端'
[2]、以及是否允许nginx使用'error_page'处理'错误'信息
补充: 假定'proxy_intercept_errors off',也即error_page暂时不处理上游的'相应状态码'
案例1:当'发生错误'的时候能够显示一个'预定义'的'uri'
备注: 通常会给其一个'静态'页面
说明: 案例1使用'普通uri',也即一旦'补获'会进行'find_location'阶段
思考: 如果'404.html'页面找不到,是否会陷入'死循环'?
建议: 保证'404.html'的'静态'页面一定存在,避免产生'其它'问题 ps: 这里404.html不存在
备注: 其他人'测试'的话,可以把'$status'也加入到里面
补充: 多个'error_page'不发生错误 ; 可以指定'多个不同的状态码'用'同一个'错误页面展示
遗留: 定义'相同状态码'在不同的error_page处理流程呢?
synax: '不加 =' 为'原错误'的状态码
案例2:当'发生错误'的时候能够显示一个'预定义'的'uri',并'显示[=200]'指定'返回状态码'
synax: [=code]
案例3:当'发生错误'的时候能够显示一个'预定义'的'uri',并通过请求'uri'的状态码作为最终状态码
synax: '='
官网'场景': uri导致反向'代理',以'后端的相应状态码'作为'最终'状态码
具体: 后端'返回'的状态码'200, 302, 401 或者 404'可以返回给'用户'
说明: 注意与'案例2'的区别
案例4:当'发生错误'的时候能够使用'@ named location'的特殊uri进行'处理'
特点: 不改变'$uri'、'request_method'、'$args'
案例5:当'发生错误'的时候,进行'[http|https]重定向地址跳转'
synax: error_page xxx ... [=[30(1|2|3|7|8)]] http[s]xxx
④ error_page深入探究
recursive_error_pages
案例1: error_page死循环'10'次
1) 默认'error_page'在一次请求中'只能响应一次',这也就是'案例1'没有进入'死循环'的原因
2) 通过'recursive_error_pages on' 控制error_page能否在一次请求中'触发多次'
备注:用'案例1'也可以做'demo'
案例2: error_page 也支持'497'等nginx自身定义的状态码
场景: 同一个端口'同时支持'http和https
nginx实现一个对外端口同时支持http和https协议访问
案例3: 移除nginx 内置 '301' 重定向行为
说明: error_page能'处理'任何'nginx'能识别的状态码,只是通常处理'非错误'状态码无意义
案例4: 设置了limit_req的'流量'限制,导致许多请求返回503错误代码,给用户'友好'提示
这里:为提高'用户体验',希望返回'正常code 200',且返回'操作频繁'的信息
淘宝limit_req_zone细讲
④ error_page和proxy_next_upstream混合使用
强调: proxy_next_upstream 这个指令可以在'上游服务器出现失败'的时候选择'其他'服务器
备注: 上游失败的判定有'以下'几种方式
原意: proxy_intercept_errors on 'on | off' --> 开启之后
[1]、当被代理的后端服务器的'响应状态码(HTTP层面)'大于300时;
[2]、决定是否'直接'将后端响应的内容直接'不经加工'的吐出发送给客户端
[3]、还是将响应转发给nginx由'error_page'来处理
备注: error_page只能处理'部分'响应状态码
1) 本节只关注 500、'502'、503、504、403、'404'、429 --> 只支持'若干个'状态码
2) $upstream_satus为'502'是什么意思? --> 此时是'error'层面的还是'http'层面的
3) 疑问: 上游服务器出问题了,nginx 还能'获取'到响应吗?
4) 本文只要探究,开启'proxy_intercept_errors on',为什么'error_page'不生效
[1]、就没有建立链接,导致'$upstream_status 502',这种是nginx填充的502
备注: 从语意上来说应该是'error'报错,所以nginx与新上游服务器建立连接,error_page不生效
[2]、后端'返回404',但是定义'http_404',proxy_next_upstream 优先级比 error_page高
备注: 遇到过镜像的第一次'认证'鉴权,由于默认proxy_next_upstream
--> 导致error_page错误'补获',进入/4xx.html,导致/被匹配,进入新的upstream
5) 明天上述三个案例'遗留'讲解
⑤