专栏首页进击的全栈nginx 常见问题记录
原创

nginx 常见问题记录

一、location 中的 if 地狱

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 语句进行条件判断怎么办呢?需要记住一下几点:

  • 当多个if条件判断同时满足时,只有最后一个if中的语句会被执行。因此若匹配前一个if语句后,不希望再往下继续匹配时,需要使用break结束;
  • proxy_pass 和 try_files 可能因为if语句不能正常执行;
  • nginx中不支持else、&& 和 || 语法,另外,nginx中if 语句也不支持嵌套,需要使用变量来构造;

二、access_log 和 error_log的路径能否使用变量?

某些场景下我们需要根据条件来区分nginx日志打印的路径,首先想到的就是能否使用如下语句呢?

access_log /home/path/${server_name}.access.log;

在高版本的nginx中允许access_log中使用变量,但是会有如下限制:

  • 日志文件用“工作进程”创建,所以需要在日志目录有创建文件的权限。
  • 无法使用写入缓冲。
  • 由于经常使用的文件描述符会被缓存,在指令open_log_file_cache的参数valid指定的时间内,还会写入旧文件中。
  • 每次写入日志时,会检查root目录是否存在。不存在,则不会创建日志。

简而言之,日志存在无法写入的可能,并且由于没有写入缓存,在请求量较大的场景会造成性能问题。

因此并不建议在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

在不了解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再次转发重试就会造成重复写入的问题。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Webassembly初识

    首先,它是一种解释性语言,大神最开始的设计目标用户就是“非专业编程人员和设计师”,避免了非专业人士对编译器了解的需要,解释性语言就是边解释边执行,与编译性语言的...

    CIKEY
  • docker 网络

    docker安装时会自动创建三个网络,我们可以用docker network ls指令查看:

    CIKEY
  • useRef 进阶

    一直以来使用useRef的场景比较常见和基础,大多是为了操作已经mount的dom节点,例如设置焦点之类的,如官方例子所示:

    CIKEY
  • tomcat请求处理分析(二) 启动mapperListener

    1.1.1启动mapperListener     这个方法的核心就是注册Host的 public void startInternal() throws L...

    cfs
  • 深入浅出理解HashMap1.8源码设计思想&手写HashMapV1.0

    数组:采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为O(1);通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O...

    须臾之余
  • 自动监控url是否可用,如不可用则重启应用,并做相应的报警策略。

    明哥的运维笔记
  • 数据访问层的使用方法

    数据访问层的使用方法。 数据访问层的使用方法 一、操作语句部分 简单的说就是传入一个操作语句,然后接收返回值就可以了。为了简化代码和提高效率,所以呢设置了五种返...

    用户1174620
  • H3C和Cisco的无线设备自动监测和重启

    背景:    前一段时间公司的购置了一批企业级的无线AP,由于使用人数太多,运行一段时间后发现,无线还是经常掉线或者无法连上网络(有线不会出现这样的问题),这...

    明哥的运维笔记
  • python获取最全ip归属地并数据库本

       user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,...

    py3study
  • 精通 Linux 上的文件搜索

    在 Linux 系统上搜索文件的方法有很多,有的命令很简单,有的很详细。我们的目标是:缩小搜索范围,找到您正在寻找的文件,又不受其他文件的干扰。在今天的文章中,...

    前端博客 : alili.tech

扫码关注云+社区

领取腾讯云代金券