Nginx 缓存命中率监控:从 X-Cache-Status 到实时统计

1 阅读1分钟

背景 上一篇配好了 Nginx 缓存,响应头里加了 X-Cache-Status,浏览器 F12 里能看到 HIT 和 MISS。

但问题来了:每次都要手动 F12,看不到整体情况。

想知道:

今天的缓存命中率是多少?

哪些请求总是 MISS?

缓存到底省了多少后端压力?

需要把 X-Cache-Status 从"单个请求可见"变成"可统计"。

原因 默认情况下,Nginx 的 $upstream_cache_status 只是一个响应头——它跟着响应发给浏览器,但不进日志。

要统计,得做两件事:

把这个变量写进 Nginx 的 access log

用脚本统计日志里的 HIT/MISS 数量

解决 第一步:定义带缓存状态的日志格式 编辑 Nginx 主配置:

sudo nano /etc/nginx/nginx.conf

在 http 块里找到 log_format 那一行,新增一个格式:

log_format cache_log '$remote_addr - [$time_local] '
                     '"$request" $status '
                     'Cache: $upstream_cache_status '
                     'Time: $request_time';

含义:

$upstream_cache_status → 就是 HIT / MISS / BYPASS

$request_time → 请求耗时,看缓存有没有真的加速

第二步:在 dashboard 配置里启用新日志

server {
    listen 8081;

    access_log /var/log/nginx/cache.log cache_log;   # 启用新日志格式

    location / {
        proxy_cache my_cache;
        add_header X-Cache-Status $upstream_cache_status;
        proxy_pass http://dashboard_cluster;
    }
}

检查 + 重启:

sudo nginx -t
sudo systemctl reload nginx

第三步:验证日志有内容

# 访问几次网站
curl -sI http://127.0.0.1:8081 > /dev/null
curl -sI http://127.0.0.1:8081 > /dev/null

# 看日志
sudo tail -5 /var/log/nginx/cache.log

预期输出:

192.168.1.1 - [06/Oct/2026:15:30:12 +0800] "GET / HTTP/1.1" 200 Cache: MISS Time: 0.025
192.168.1.1 - [06/Oct/2026:15:30:13 +0800] "GET / HTTP/1.1" 200 Cache: HIT Time: 0.001

Time 那一列:HIT 的耗时是 MISS 的 1/20 —— 缓存的加速效果一目了然。 第四步:写统计脚本

#!/bin/bash
# cache-stats.sh

LOG="/var/log/nginx/cache.log"

TOTAL=$(sudo grep -c "Cache:" "$LOG")
HIT=$(sudo grep -c "Cache: HIT" "$LOG")
MISS=$(sudo grep -c "Cache: MISS" "$LOG")
BYPASS=$(sudo grep -c "Cache: BYPASS" "$LOG")

if [ "$TOTAL" -eq 0 ]; then
    echo "日志为空"
    exit 0
fi

RATE=$(awk "BEGIN {printf \"%.1f\", $HIT / $TOTAL * 100}")

echo "================================"
echo "  缓存命中率统计"
echo "================================"
echo "总请求:  $TOTAL"
echo "HIT:     $HIT"
echo "MISS:    $MISS"
echo "BYPASS:  $BYPASS"
echo "命中率:  $RATE%"
echo "================================"

运行:

chmod +x cache-stats.sh
./cache-stats.sh

预期输出:

================================
  缓存命中率统计
================================
总请求:  1250
HIT:     1032
MISS:    218
BYPASS:  0
命中率:  82.6%
================================

第五步:加到定时任务

crontab -e

每天 8 点输出一次统计,追加到日志:

0 8 * * * /home/YOUR_USER/cache-stats.sh >> /home/YOUR_USER/cache-stats.log 2>&1

三个坑 坑 1:忘了在 server 块里启用新日志格式

只在 http 里定义了 log_format 不够,每个 server 块要显式指定 access_log ... cache_log。不写,默认还是走 combined 格式,里面没有缓存状态。

坑 2:日志无限增长

加了新日志后,/var/log/nginx/cache.log 会一直涨。要配 logrotate:

sudo nano /etc/logrotate.d/nginx-cache

写入:

/var/log/nginx/cache.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
}

不配的话,跑几个月日志能到几十 GB。

坑 3:只看命中率不看时间

命中率 80% 听起来不错,但如果 MISS 的都是慢请求,用户体验还是很差。

要看两个维度:

命中率(HIT / TOTAL)

HIT 和 MISS 的平均耗时对比

# MISS 的平均耗时
sudo grep "Cache: MISS" /var/log/nginx/cache.log | \
  awk '{print $NF}' | awk -F: '{sum+=$2; n++} END {print sum/n}'