Directive if has problems when used in location context, in some cases it doesn’t do what you expect but something completely different instead. In some cases it even segfaults. It’s generally a good idea to avoid it if possible.
The only 100% safe things which may be done inside if in a location context are:
return ...;
rewrite ... last;
官方文档指明,location if语句中只有实用return 和 rewrite指令是绝对安全的。但是如果某些情况必须使用if 语句进行条件判断怎么办呢?需要记住一下几点:
某些场景下我们需要根据条件来区分nginx日志打印的路径,首先想到的就是能否使用如下语句呢?
access_log /home/path/${server_name}.access.log;
在高版本的nginx中允许access_log中使用变量,但是会有如下限制:
简而言之,日志存在无法写入的可能,并且由于没有写入缓存,在请求量较大的场景会造成性能问题。
因此并不建议在access_log的路径中使用变量名。那怎样才能满足分不同路径打印的需求呢?access_log 支持可选参数 if=condition, 例如下面的官方例子,当返回码为2xx或3xx时不会打印日志,其他情况下的日志会打印到/path/to/access.log文件中:
map $status $loggable {
~^[23] 0;
default 1;
}
access_log /path/to/access.log combined if=$loggable;
error_log 路径不支持变量。变量一般是在http请求中使用,而error_log并不限于http请求使用,且应该保证所有关键的错误日志都能打印成功,便于定位问题。
在nginx中使用自定义头部不限制字母的大小写,但需要注意尽量使用中划线,若在必须使用下划线的情况下,需要设置 underscores_in_headers on;否则nginx会认为该头部不合法,由 ignore_invalid_headers 指令判断是否忽略该头部。
nginx读取自定义头部的变量为$http_{name}, name为头部名称的小写,且用下划线代替中划线即可。
在不了解proxy_next_upstream机制时可能会踩到很多坑,比如服务出现了错误或超时,nginx却没有按照预期自动进行重试;或者类似创建订单或支付类的写接口,客户端明明只发送了一次请求,却因为nginx的重试,后台创建了多个相同的订单而引发线网问题等。
proxy_next_upstream指令指明了请求在什么情况会被重新发送到另外的server。
默认只有当连接上游服务出错或者超时时会重试,若需要对某些特定的http状态码进行重试,则需要指定http_500、http_404等。
但是通常情况下POST, LOCK, PATCH方法不会被转发到另一台server重试,需要显示设置non_idempotent才行。
但是生产环境一般不建议开启non_idempotent,无论是timeout还是http_500都可能是后台已经接受过一次请求了,若nginx再次转发重试就会造成重复写入的问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。