我有一个主 nginx.conf,其中包含我其余的服务器(服务器块) 使用 include 指令:
include myservers/*.conf;
我的问题是,当我在 myservers/ 中有一个新的配置文件时,我需要重新加载 nginxnginx -s reload
问题需要很长时间才能重新加载服务器需要 1 分钟,而且这个时间还会增长,因为我将拥有更多上游服务器。
您是否看到任何可以改善这一情况的技术?
目前我发现的唯一解决方案是付费版本的 Nginx Nginx Plus APIhttps://docs.nginx.com/nginx/admin-guide/load-balancer/dynamic-configuration-api/您可以使用 REST API 动态添加新的上游服务器,而无需任何重新加载。
另外,我正在考虑采用一种分片技术,其中一个主服务器带有哈希键到从服务器(就像使用 RAFT 算法来保持共识状态的 elasticsearch 一样),这样当您需要更新时,您只需重新加载一个具有较少上游服务器的从服务器。
答案1
您有多少个文件以及什么样的配置,nginx -s reload
需要整整一分钟的时间?!
识别来源。
我认为你必须首先弄清楚为什么它会花费这么长时间,然后才能找到解决方案。
文件系统问题?
是不是因为单个文件的数量过多,导致进程变慢了?
例如,做一件事
cat myservers/*.conf | md5
本身就需要一分钟吗?如果是这样,您可能需要考虑使用 ramdisk 进行配置;或者将各个配置保存在数据库中,并使用单个配置
nginx.conf
用于重新加载目的。
配置指令问题?
配置文件的内容是否需要很长时间才能重新加载?
这个问题可能由多种原因造成。
例如,您的某个配置可能使用了需要很长时间才能解析的域名(超时),从而减慢了整个重新加载过程。这可能是您的设置中的一个安全漏洞,因为单个用户可能会在输入“正确”的情况下减慢整个重新加载过程。
这也可能是配置的另一个问题,可能是因为需要关闭/打开太多单独的日志文件。您可以使用以下工具进一步了解此问题
lsof
和/或fstat
,查看应用程序打开的文件数。
这真是一个问题吗?
正如其他人指出的那样,即使按原样,这也已经不是一个大问题了,因为这
nginx -s reload
是一个正常重新加载配置的过程,即使您正在重新加载其配置,nginx 仍然应该保持完全正常运行。我认为将重新加载设计成批处理并每 5 到 15 分钟执行一次重新加载是完全合理的。如果您正在处理新域名,您可能已经必须等到配置在 DNS 级别开始工作。长达 1 分钟的延迟一点也不不合理,并且至今仍经常在各种云提供商的生产服务中实现。事实上,DNS 根区域通常也以批处理模式更新,通常以远低于每 15 分钟一次的频率更新,特别是考虑到所涉及的数据量巨大;例如,每天
.ru
仅刷新 4 次,因为它有 500 万条记录,并且由几个单独的提供商镜像以实现冗余,每次更新都需要最多 30 分钟,因此它们必须分开以确保合理的一致性,并确保单独的更新不会相互冲突。如果您需要立即使更改生效,那么可能需要不同的架构;也许提供一个单独的暂存区来测试配置,或者采用多层方法,或者采用商业版本的 nginx 和/或第三方插件。
想出一个解决方案。
根据问题的根源,解决方案是重新设计配置方式。
如果不知道问题的根源,这个问题就太宽泛,无法提供任何具体的建议。
答案2
我启动了一个新的虚拟机(带有 SSD 支持存储)并在其上安装了 nginx。然后我编写了一个脚本来生成大量文件,每个文件包含一个server
块。它们看起来很像这样:
[root@localhost ~]# cat /etc/nginx/sites/server047393.conf
server {
listen 80;
listen [::]:80;
server_name server047393;
}
起初我创建了 50,000 个,但重新加载 nginx 仅需 9 秒,因此我将其增加到 100,000 个。这样,重新加载 nginx 始终需要 20 秒。这段时间的前半部分用于等待磁盘 I/O,后半部分用于等待 CPU。有了这么多的服务器块,nginx 使用了近 1GiB 的 RAM。
这看起来真的不是什么问题,除非你的 nginx 配置位于一个非常慢的磁盘上。当你重新加载或重新启动 nginx 时,它会被重新读取。使用旋转磁盘,重新加载很容易需要几分钟。使用 SSD 甚至 RAM 磁盘来存储 nginx 配置。
确实,nginx 自己的服务器名称的优化建议几乎没有提到配置解析时间。这实际上不是你应该非常关心的事情。它确实经常谈论的是定位正确块来处理传入请求所需的时间server
。默认情况下,nginx 会尝试优化这一点以最大限度地减少 CPU 缓存行未命中。
为了针对大量服务器名称进行优化,您可能不需要执行任何操作,但可能需要调整指令server_names_hash_max_size
。运行nginx -t
。如果您看到如下消息:
nginx: [warn] could not build optimal server_names_hash, you should increase either server_names_hash_max_size: 512 or server_names_hash_bucket_size: 64; ignoring server_names_hash_bucket_size
然后您应该调整server_names_hash_max_size
。首先将其设置为比您要创建的 s 数量大的 2 的幂server_name
。如果您有 30,000 个服务器名称,请从 开始server_names_hash_max_size 32768
。
优化文档确实提到:
如果 nginx 的启动时间太长,无法接受,请尝试增加
server_names_hash_bucket_size
。
我在测试中发现这并没有真正起到作用,但如果你想尝试一下,每次都将其增加 2 的幂。此值必须是 2 的幂,否则 nginx 将无法启动。此值默认根据 CPU 缓存行大小设置,因此如果你在虚拟机上,并且 CPU 属性未正确暴露给虚拟机,你可能可以安全地将此数字加倍(或者 nginx 一开始就拒绝启动,但这是一个略有不同的错误消息,could not build the server_names_hash
)。不要过度使用它,否则你的传入请求将因 CPU 缓存未命中而变慢。
答案3
显而易见的(幼稚的)方法是使用虚拟硬盘,然后设置定期备份。这可以通过某种钩子来安排或触发,例如,当用户在 cPanel 或其他东西中进行更改时,它会触发备份。
对此的一个变体是强制将整个目录视为缓存,例如虚拟触摸。
也可以将配置的某些部分移动到数据库中,例如ngx_postgres。如果 nginx 支持从 DB 加载完整配置那就更好了,但我不知道有这样的事。
答案4
这种非常动态的方法怎么样?它确实采取了减少配置文件数量的方向。根据您的要求,这可能是一种前进的方式: