Varnish存储配置、性能优化及运行故障排查问题咨询
Varnish 6.0 生产环境配置优化参考
当前生产环境运行Varnish社区版
6.0.1,原启动配置如下:varnishd -F -j unix,user=nobody -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -s file,/opt/varnishdata/cache,500G缓存对象均为JSON格式,单对象大小从数字节到1MB不等,实际缓存规模含预留不超过30G,服务器总内存32G。
存储配置类问题
- 500G file存储容量是否需要缩减
必须缩减,建议配到40G即可。6.0版本的file存储基于mmap实现,哪怕实际缓存数据远低于配置阈值,启动时就会为配置的全量容量预分配缓存索引元数据,500G配置光索引就要吃掉近5G内存,完全是无意义的开销。你实际缓存规模含预留才30G,留10G冗余应对小对象存储碎片、突发流量新增缓存完全足够,过大的存储配置还会拉长缓存淘汰扫描的遍历周期,提升不必要的磁盘IO开销。 - malloc替换file、混合存储是否可行
不要全量换malloc,原生不支持自动冷热分层,手动配置混合存储收益最高。malloc是纯内存存储,访问延迟为亚毫秒级,比走磁盘mmap的file存储快5~10倍,但你服务器总内存只有32G,全量换malloc存30G数据的话,算上Varnish线程栈、工作区、索引元数据、系统内核预留的内存,必然触发swap,只要出现swap换页,Varnish多线程模型会因为缺页中断直接出现全局阻塞,性能比纯file存储还差。
正确的配置方式是配2224G的malloc存储,搭配16G的file存储,总存储容量3840G和之前建议的冗余值匹配;同时在VCL里写规则,将小于10KB的JSON对象、高频访问接口的响应优先存入malloc,大对象、低频访问响应存入file,手动实现热数据内存驻留。另外必须把系统的vm.swappiness参数设为0,彻底避免内核把Varnish占用的内存页换出到磁盘。
注意:Varnish原生没有自动冷热分层能力,不要指望配两个存储引擎它自己帮你调度热数据,必须自己在vcl_backend_response里通过set beresp.storage = storage.malloc;这类逻辑指定存储位置。
功能模块与故障排查类问题
- xkey替换为ykey的收益问题
6.0.1版本完全没必要换。xkey是Varnish官方维护的标签失效模块,和6.0 LTS系列的适配经过了大规模生产验证,稳定性有保障。ykey是第三方fork的优化版本,核心收益是在缓存key规模过亿、单批次失效标签量过十万的场景下,降低内存占用和失效耗时,你当前总缓存才30G,单对象最大1MB,总key规模撑死几百万,xkey的性能冗余足够,换ykey不会有可感知的收益,反而要承担第三方模块和6.0.1小版本适配不完善带来的内存泄漏、失效不准的风险。 - 连接突增/羊群效应下的延迟上涨、后端获取失败排查方向
按优先级从高到低排查:- 线程池参数:默认配置的线程数上限、队列长度完全扛不住突发流量。6.0版本建议配置
thread_pools=2(和物理CPU核数对齐,最多不超过4),thread_pool_min=200,thread_pool_max=5000,thread_queue_limit=200。重点看MAIN.threads_limited、MAIN.sess_queued两个指标,如果突增时这两个值跳涨,说明工作线程不够,请求在队列排队,直接导致延迟上涨,队列满了就会直接丢请求报后端获取失败。 - 后端连接池配置:默认的后端连接数限制非常容易在突增时打满。给每个后端配置
.max_connections为后端实际承载能力的80%,超时参数设为.connect_timeout=1s、.first_byte_timeout=3s、.between_bytes_timeout=2s,避免慢连接占满整个连接池。重点看MAIN.backend_busy、MAIN.backend_unhealthy指标,如果这两个值突增,要么是连接池打满无法新建后端请求,要么是慢请求太多导致后端被标记为不健康。 - 缓存击穿防护:羊群效应本质是热点key过期瞬间,大量同key请求同时穿透到后端,Varnish默认的请求合并机制会让大量请求排队等第一个回源请求返回,排队超时就会报错。建议在VCL里给热点接口配置
stale-while-revalidate=30s,缓存过期后先给客户端返回旧缓存,后台异步回源更新,从根源避免大量请求同时等回源。 - 存储IO瓶颈:如果用file存储,突增时如果磁盘util跑满100%,mmap缺页的请求会全部阻塞,直接导致延迟飙升、后端超时,这也是之前建议大比例配malloc存储的核心原因。
- 线程池参数:默认配置的线程数上限、队列长度完全扛不住突发流量。6.0版本建议配置
其他可落地的优化建议
- 尽快升级6.0系列的最新小版本,6.0.1存在已知的file存储元数据损坏、内存泄漏bug,小版本升级完全兼容现有配置,不需要改业务逻辑。
- 因为你缓存的对象最大才1MB,启动参数加
-p fetch_maxchunksize=1m,限制单缓存对象最大大小,避免异常大对象占满存储空间。 - 开启JSON响应的gzip压缩,JSON文本压缩率普遍在70%以上,能直接省出三分之二的缓存空间,同时提升响应传输速度。
- 不要全量打印访问日志,高并发下日志写盘IO会抢占存储带宽,开10%采样足够排查日常问题。
内容的提问来源于stack exchange,提问作者Abhishek Surve
相关产品推荐
相关产品推荐

