关于配置:避免-10-大-NGINX-配置错误上

44次阅读

共计 5717 个字符,预计需要花费 15 分钟才能阅读完成。

原文作者:Timo Stark of F5, Sergey Budnevich of F5
原文链接:防止 10 大 NGINX 配置谬误
转载起源:NGINX 官方网站


在帮忙 NGINX 用户解决问题时,咱们常常会发现配置谬误,这种配置谬误也每每呈现在其余用户的配置中,甚至有时还会呈现在咱们的 NGINX 工程师共事编写的配置中!本文介绍了 10 个最常见的谬误,并解释了问题所在以及相应的解决办法。

1. 每个 worker 的文件描述符有余
2.error_log off 指令
3. 未启用与上游服务器的 keepalive 连贯
4. 遗记指令继承的工作机制
5.proxy_buffering off 指令
6.if 指令使用不当
7. 过多的健康检查
8. 不平安地拜访指标
9. 当所有流量都来自同一个 /24 CIDR 块时应用 ip_hash
10. 不采纳上游组

谬误 1:每个 worker 没有足够的文件描述符

worker_connections 指令用于设置 NGINX worker 过程能够关上的最大并发连接数(默认为 512)。所有类型的连贯(例如与代理服务器的连贯)都计入最大值,而不仅仅是客户端连贯。但重要的是要记住,最终每个 worker 的并发连接数还有另一个限度:操作系统对调配给每个过程的文件描述符 (file descriptor,即 FD) 最大数量的限度。在古代 UNIX 发行版中,默认限度为 1024。

对于除最小的 NGINX 部署之外的 所有部署,将每个 worker 的连接数限度为 512 可能太少了。事实上,咱们将随 NGINX 开源版二进制文件和 NGINX Plus 一起散发的默认 nginx.conf 文件将其减少到 1024。

常见的配置谬误是没有将 FD 的限度减少到至多两倍的 worker_connections 的值。解决办法是在主配置上下文中应用 worker_rlimit_nofile 指令设置该值。

这就是须要更多 FD 的起因:从 NGINX worker 过程到客户端或上游服务器的每个连贯都耗费一个 FD。当 NGINX 充当 Web 服务器时,每个客户端连贯应用一个 FD,每个服务的文件应用一个 FD,这样每个客户端至多需两个 FD(但大多数网页是由许多文件构建的)。当充当代理服务器时,NGINX 别离应用一个 FD 连贯客户端和上游服务器,并可能用到第三个 FD 给用于长期存储服务器响应的文件。作为缓存服务器时,NGINX 的行为相似于缓存响应的 Web 服务器,如果缓存为空或过期,则相似于代理服务器。

NGINX 为每个日志文件应用一个 FD,并会用几个 FD 与主过程通信,但与用于连贯和文件的 FD 数量相比,这些数量通常很少。
UNIX 提供了几种办法来设置每个过程的 FD 数量:

  • 如果从 shell 启动 NGINX,则应用 ulimit 命令
  • 如果将 NGINX 作为服务启动,则应用 init 脚本或 systemd 服务清单变量
  • /etc/security/limits.conf 文件

应用的办法取决于您如何启动 NGINX,而 worker_rlimit_nofile 与您启动 NGINX 的形式无关。

FD 的数量也有零碎范畴的限度,您能够应用操作系统的 sysctl fs.file-max 命令进行设置。它通常足够大,但有必要验证所有 NGINX worker 过程可能应用的文件描述符的最大数量 (worker_rlimit_nofile * worker_processes) 显著小于 fs.file‑max。如果 NGINX 以某种形式应用了所有可用的 FD(例如,在 DoS 攻打期间),此时甚至都无奈登录机器来解决问题。

谬误 2:error_log off 指令

常见的谬误是认为 error_log off 指令会禁用日志记录。事实上,与 access_log 指令不同,error_log 不蕴含 off 参数。如果在配置中增加了 error_log off 指令,则 NGINX 会在 NGINX 配置文件的默认目录(通常是 /etc/nginx)中创立一个名为 off 的谬误日志文件。

咱们不倡议禁用谬误日志,因为它是调试 NGINX 任何问题时的重要信息起源。然而,如果存储空间十分无限,记录的数据可能足以耗尽可用的磁盘空间,此时禁用谬误日志记录可能有意义。在主配置上下文中蕴含该指令:

error_log /dev/null emerg;

请留神,在 NGINX 读取并验证配置之前,该指令不会利用。因而,每次 NGINX 启动或从新加载配置时,它可能会记录到默认的谬误日志地位(通常为/var/log/nginx/error.log),直到配置验证后。更改日志目录的办法是,在 nginx 命令中增加 -e <error_log_location> 参数。

谬误 3:未启用与上游服务器的 keepalive 连贯

默认状况下,NGINX 会为每个新的传入申请关上一个到上游(后端)服务器的新连贯。这种操作尽管平安然而低效,因为 NGINX 和服务器必须替换三个数据包来建设连贯,并替换三个或四个数据包来终止连贯。

在流量高峰期,为每个申请关上一个新连贯会耗尽系统资源,最终导致根本无法关上连贯。起因是:对于每个连贯,源地址、源端口、指标地址和指标端口的 4 元组必须是惟一的。对于从 NGINX 到上游服务器的连贯,四元组中的三个(第一个、第三个和第四个)是固定的,只有源端口是变量。当连贯敞开时,Linux 套接字会处于 TIME‑WAIT 状态两分钟,在流量高峰期时这会减少可用源端口池耗尽的可能性。如果产生这种状况,NGINX 将无奈关上与上游服务器的新连贯。

解决办法是在 NGINX 和上游服务器之间启用 keepalive 连贯 —— 该连贯不会在申请实现时敞开,而是放弃关上状态以用于其余申请。这样做既升高了源端口耗尽的可能性,又进步了性能。

启用 keepalive 连贯的办法是:

  • 在每个 upstream{} 块中蕴含 keepalive 指令,以设置保留在每个 worker 过程缓存中的到上游服务器的闲暇 keepalive 连接数。

    请留神,keepalive 指令不限度 NGINX worker 过程能够关上的上游服务器的连贯总数——这一点常常被误会。所以 keepalive 的参数不须要像您设想的那么大。

    咱们倡议将该参数设置为 upstream{} 块中列出的服务器数量的两倍。这足以让 NGINX 放弃与所有服务器的 keepalive 连贯,同时也足够小,上游服务器还能够解决新的传入连贯。

    另请留神,当您在 upstream{} 块中指定负载平衡算法时 —— 应用 hash、ip_hash、least_conn、least_time 或 random 指令 —— 该指令必须位于 keepalive 指令之前。通常,在 NGINX 配置中,指令程序并不重要,而这是多数例外之一。

  • 在将申请转发到上游 group 的 location{} 块中,增加以下指令以及 proxy_pass 指令:
proxy_http_version 1.1;
proxy_set_header   "Connection" "";

NGINX 默认应用 HTTP/1.0 连贯上游服务器,并相应地将 Connection: close 标头增加到它所转发到服务器的申请中。这样只管 upstream{} 块中蕴含了 keepalive 指令,但每个连贯依然会在申请实现时敞开。

proxy_http_version 指令告知 NGINX 应用 HTTP/1.1,proxy_set_header 指令将从 Connection 标头中删除 close 值。

谬误 4:遗记指令继承的工作机制

NGINX 指令是向下继承的,或者是“由外而内”继承的:一个子上下文(一个嵌套在另一个上下文,即父上下文中的上下文)继承父上下文蕴含的指令的设置。例如,http{} 上下文中的所有 server{} 和 location{} 块都继承了蕴含在 http 级别的指令的值,并且 server{} 块中的指令被它的所有子 location{} 块继承。然而,当父上下文及其子上下文中蕴含雷同的指令时,这些值不会相加 —— 相同,子上下文中的值会笼罩父上下文中的值。

常见的谬误是遗记了这种数组指令的“笼罩规定”,它不仅能够蕴含在多个上下文中,而且还能够在给定上下文中蕴含屡次。例如 proxy_set_header 和 add_header —— 第二个名称中蕴含“add”导致笼罩规定很容易被遗记。

咱们能够通过 add_header 的例子来阐明继承的工作机制:

http {
    add_header X-HTTP-LEVEL-HEADER 1;
    add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

    server {
        listen 8080;
        location / {return 200 "OK";} 
    }

    server {
        listen 8081;
        add_header X-SERVER-LEVEL-HEADER 1;

        location / {return 200 "OK";}

        location /test {
            add_header X-LOCATION-LEVEL-HEADER 1;
            return 200 "OK";
        }

        location /correct {
            add_header X-HTTP-LEVEL-HEADER 1;
            add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

            add_header X-SERVER-LEVEL-HEADER 1;
            add_header X-LOCATION-LEVEL-HEADER 1;
            return 200 "OK";
        } 
    }
}

对于监听端口 8080 的服务器,server{} 或 location{} 块中都没有 add_header 指令。所以继承很简略,咱们看到 http{} 上下文中定义了上面两个 http 音讯头:

% curl -is localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:15 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-HTTP-LEVEL-HEADER: 1
X-ANOTHER-HTTP-LEVEL-HEADER: 1
OK

对于监听端口 8081 的服务器,server{} 块中有一个 add_header 指令,但其子 location / 块中没有该指令。server{} 块中定义的音讯头笼罩了 http{} 上下文中定义的两个 http 音讯头:

% curl -is localhost:8081
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:20 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-SERVER-LEVEL-HEADER: 1
OK

在子 location /test 块中,有一个 add_header 指令,该指令笼罩了其父 server{} 块中的 http 音讯头和 http{} 上下文中的两个 http 音讯头:

% curl -is localhost:8081/test
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:25 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-LOCATION-LEVEL-HEADER: 1
OK

如果咱们心愿 location{} 块保留其父上下文中定义的 http 音讯头以及本地定义的任何 http 音讯头,咱们必须在 location{} 块中从新定义父 http 音讯头。这就是咱们在 location /correct 块中所做的:

% curl -is localhost:8081/correct
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:30 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-HTTP-LEVEL-HEADER: 1
X-ANOTHER-HTTP-LEVEL-HEADER: 1
X-SERVER-LEVEL-HEADER: 1
X-LOCATION-LEVEL-HEADER: 1
OK

谬误 5:proxy_buffering off 指令

NGINX 默认启用代理缓冲(proxy_buffering 指令设置为 on)。代理缓冲意味着 NGINX 将来自服务器的响应存储在外部缓冲区中,并且在整个响应被缓冲之后才开始向客户端发送数据。缓冲有助于优化慢速客户端的性能 —— 因为 NGINX 缓冲响应的工夫与客户端检索所有响应的工夫一样长,代理服务器能够尽可能快地返回响应,而后返回到可用的状态以响应其余申请。

如果代理缓冲被禁用,则 NGINX 只会在默认为一个内存页大小(4 KB 或 8 KB,具体取决于操作系统)的缓冲区内缓存服务器响应的结尾局部后就开始向客户端传输。通常,这个缓存空间只够缓存响应 http 音讯头。NGINX 收到响应后会同步发送给客户端,迫使服务器处于闲暇状态,直到 NGINX 能够承受下一个响应段为止。

因而,对于常常在 NGINX 配置中看到 proxy_buffering off 指令的状况,咱们感到十分诧异。兴许这样做是为了缩小客户端提早,但其影响能够忽略不计,而敞开后的副作用却很多:代理缓冲被禁用后,速率限度和缓存即使配置了也不起作用,性能也会受影响等等。

只有在多数状况下,禁用代理缓冲可能有意义(例如长轮询),因而咱们强烈建议不要更改默认设置。无关更多信息,请参阅《NGINX Plus 治理指南》。

如欲试用 NGINX Plus,请立刻下载 30 天收费试用版,或与咱们分割以探讨您的用例。


更多资源
想要更及时全面地获取 NGINX 相干的技术干货、互动问答、系列课程、流动资源?

请返回 NGINX 开源社区:

  • 官网:www.nginx.org.cn/
  • 微信公众号:mp.weixin.qq.com/s/XVE5yvDbm…
  • 微信群:www.nginx.org.cn/static/pc/i…
  • B 站:space.bilibili.com/628384319

正文完
 0