这是我的 Varnish 配置:

/usr/sbin/varnishd \
      -a 127.0.0.1:6081 \
      -T 127.0.0.1:6082 \
      -f /varnish/default.vcl \
      -P %t/%N/varnishd.pid \
      -s malloc,4G \
      -p thread_pools=12 -p thread_pool_min=250 -p default_ttl=1 -p default_grace=0 -p timeout_idle=1800

因此 12 * 250 = 3000 个线程。使用此设置,我最终打开了超过 400k 个文件。

将线程数减少到最低限度确实会大大减少打开文件的数量。

问题是:这怎么可能?每个 Varnish 线程打开这么多文件是正常的吗?


最佳答案
1

您设置的某些参数可能是导致打开文件数量过多的原因。

线程

让我们从 开始thread_pools=12。默认值为 2,我们不建议您更改它。虽然在您的用例中thread_pool_min设置为250,但 的默认thread_pool_max值为5000

问题是:“在高峰流量期间,或者甚至在活动线程数远低于 1000 个时,您是否看到 40 万个打开的文件?”

仅供参考:MAIN.threads计数器varnishstat可以帮助您确定有多少个活动线程。

假设这种情况发生在绝对峰值流量期间,每个池有 5,000 个线程,但 12 个线程池产生 60,000 个活动线程。

这意味着每个线程大约有 7 个文件描述符,这并不不合理。

影响timeout_idle

当然,还有一个参数,你可以将其从 5 增加到 1800。这意味着,如果设置了keepalive,则连接将空闲 1800 秒,然后关闭。

那真是很长一段时间了。

空闲连接的文件描述符从线程中移出,并由等待线程管理。这意味着文件描述符被保留,而线程可以接受新的连接并创建更多的文件描述符。

仅供参考:您可以运行varnishstat -f "WAITER.*.conns" -f "MAIN.sess_conn" -f "MAIN.backend_conn"来监视由服务员线程处理的连接、常规传入连接和后端连接。

需要进行更多调试

在我的回答中,我假设 400k 个打开的文件发生在高峰流量期间。如果不是这样,则需要进行更多调试才能确定哪些文件(或文件描述符)正在使用中。

其中一种方法是运行以下命令:

lsof -p $(pgrep cache-main)

此命令将列出该进程正在使用的各种文件描述符。

当然,运行以下命令并结合参数来列出所有线程和连接:

varnishstat -f "MAIN.threads" -f "WAITER.*.conns" -f "MAIN.sess_conn" -f "MAIN.backend_conn"

3

  • 谢谢你的回答。我设置thread_pools=12为减少锁争用(我的服务器上有 12 个核心)。Varnish 手册建议此值不应大于核心数。设置thread_pool_min=1500thread_pools=2结果为打开文件数相同。我提到的 400k 个打开文件不是在高峰流量期间:它是永久的。我有一个没有流量的备份服务器,我仍然有超过 400k 个打开文件。lsof -p $(pgrep cache-main) | wc -l仅返回 ~150。


    – 

  • 另外,关于timeout_idle:这是因为我有一个本地 NGINX 为客户端提供服务,并且只将 EXPIRED 请求转发给 Varnish,因为 Varnish 可以压缩 EXPIRED 请求。Varnish 只接受来自本地 NGINX 的连接(因此选项 -a 和 -T)


    – 


  • 事实上,在我的主服务器上,timeout_idle没有设置(默认为 5 秒),我将其设置为 1800 进行一些测试。不过,使用默认值时,我仍然有同样多的打开文件


    –