文章页更新不频繁,在nginx上开一层proxy_cache顶住流量是最省事的做法。配置加完、缓存目录建好、nginx -t通过、reload也没报错,刷新页面十几次,缓存状态一直停在MISS。这时候容易往两个方向想,要么觉得缓存目录权限不对,要么怀疑proxy_cache_path的路径写错了。这两处真有问题,nginx根本起不来,能正常启动就说明它们没毛病。剩下的可能性集中在四处:上游的响应头、Set-Cookie、缓存键怎么拼、各类响应的缓存时长。
log_format里加一个$upstream_cache_status,日志就会多出一列,值是HIT、MISS、BYPASS、EXPIRED、STALE之一。MISS是请求到了后端却没落缓存,BYPASS是被规则直接跳过,两者要查的地方不同。BYPASS通常是location里写了跳过缓存的判断,先去看那一段。
第一处在上游的响应头。nginx默认尊重后端发来的缓存指令,响应里只要带Cache-Control的no-cache、no-store或者private,这份响应就不会被存下来。WordPress默认给页面带上no-cache相关头,PHP会话一开更是如此,缓存键配得再对也白搭。用curl -I打一条请求,把响应头完整看一遍就能确认,重点看Cache-Control和Expires两行。
第二处是Set-Cookie。响应头里一出现这个字段,nginx同样跳过缓存,原因是它没法判断这份内容是不是和某个用户的身份绑在一起,宁可每次都回源。wordpress_logged_in这类Cookie要格外留心,登录态和游客态走的是同一个URL,缓存混用的话,甲刷出乙的用户名是迟早的事。要让缓存落地,得先让上游按登录态分流,比如只对未登录访客返回可缓存版本,或者用proxy_ignore_headers把Set-Cookie和Vary放行,同时接受由此带来的串号风险。这一步是取舍,不是纯粹的配置问题。
第三处是缓存键。proxy_cache_key的默认值是$scheme$proxy_host$request_uri,含义是带不同查询参数的URL各占一份缓存。文章页地址通常很干净,可评论分页、站内搜索、带utm标记的分享链接会把它切成一堆碎片,每块只被访问一次,命中率自然上不去。
proxy_cache_valid管的是各类响应的缓存时长,只写时间、不跟状态码时,nginx只缓存200、301、302三种响应,页面返回404或者502,配置看着没问题,实际一条都没存。不写这条指令时,nginx只按上游响应头里给的时长缓存,后端不给时长就一条都不存。
改完连打两次同一个地址,中间隔几秒,第一次该是MISS,第二次变成HIT,响应头里的Age开始往上走。两次都是MISS,就把响应头完整打出来,对照上面四处逐个核。缓存目录里也能验证,落盘的文件名就是缓存键算出来的哈希。
A5创业网 版权所有