首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Linux Varnish 快取配置優化完整指南:安裝、VCL、後端、健康檢查、日誌、核心調優

     編輯:PHP 綜合知識

前言

Varnish Cache 是高效能 HTTP 反向代理快取,廣泛用於動態網站加速。本文提供從原始碼編譯安裝、VCL 配置詳解、後端負載均衡、健康檢查、日誌切割、Linux 核心參數調優到管理操作的完整實戰指南。

編譯安裝 (RedHat/CentOS 7 範例)

# 1. 安裝依賴
yum install -y gcc make autoconf automake libtool pkgconfig \
    python3-docutils pcre-devel libedit-devel

# 2. 下載原始碼 (以 6.6 LTS 為例)
wget https://varnish-cache.org/_downloads/varnish-6.6.2.tgz
tar xzf varnish-6.6.2.tgz
cd varnish-6.6.2

# 3. 配置編譯
./configure --prefix=/usr/local/varnish-6.6.2
make -j$(nproc)
make install

# 4. 建立軟連結方便管理
ln -s /usr/local/varnish-6.6.2 /usr/local/varnish
ln -s /usr/local/varnish/sbin/varnishd /usr/sbin/varnishd
ln -s /usr/local/varnish/bin/* /usr/bin/

VCL 配置檔詳解 (/usr/local/varnish/etc/varnish/default.vcl)

後端伺服器定義與健康檢查

vcl 4.1;

# 後端定義
backend web01 {
    .host = "192.168.1.101";
    .port = "8080";
    .probe = {
        .url = "/healthz";
        .timeout = 2s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
        .expected_response = 200;
    }
    .connect_timeout = 1s;
    .first_byte_timeout = 5s;
    .between_bytes_timeout = 2s;
}

backend web02 {
    .host = "192.168.1.102";
    .port = "8080";
    .probe = {
        .url = "/healthz";
        .timeout = 2s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

# 負載均衡器:隨機權重
director app_cluster random {
    .retries = 3;
    {
        .backend = web01;
        .weight = 3; # 權重 3
    }
    {
        .backend = web02;
        .weight = 1; # 權重 1
    }
}

# 另一種:輪詢
# director app_cluster round_robin { ... }

ACL 存取控制

acl purge_allowed {
    "localhost";
    "127.0.0.1";
    "10.0.0.0/8";      # 內網管理網段
    "192.168.0.0/16";
}

核心子程式:vcl_recv (請求進入點)

sub vcl_recv {
    # 1. 正規化 Host header
    set req.http.Host = regsub(req.http.Host, ":.*$", "");

    # 2. 指定後端
    if (req.http.host ~ "^(www\.)?example\.com$") {
        set req.backend_hint = app_cluster;
    } else {
        return (synth(404, "Unknown domain"));
    }

    # 3. PURGE 請求驗證
    if (req.method == "PURGE") {
        if (!client.ip ~ purge_allowed) {
            return (synth(405, "Not allowed"));
        }
        return (purge);
    }

    # 4. 移除靜態資源 Cookie (提高快取命中)
    if (req.url ~ "\.(css|js|jpg|jpeg|png|gif|ico|woff|woff2|svg|webp)(\?.*)?$") {
        unset req.http.Cookie;
    }

    # 5. 保留原始客戶端 IP (X-Forwarded-For)
    if (req.http.X-Forwarded-For) {
        set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
    } else {
        set req.http.X-Forwarded-For = client.ip;
    }

    # 6. 非 GET/HEAD 請求不快取 (POST/PUT/DELETE 等)
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    # 7. 動態頁面不快取 (含 Cookie、Authorization)
    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }

    # 8. 特定路徑不快取 (如管理後台、API)
    if (req.url ~ "^/(admin|api|user)/") {
        return (pass);
    }

    # 9. 預設查詢快取
    return (hash);
}

vcl_backend_response (後端回應處理)

sub vcl_backend_response {
    # 1. 後端明確禁止快取
    if (beresp.http.Cache-Control ~ "(no-cache|no-store|private)" ||
        beresp.http.Pragma ~ "no-cache") {
        set beresp.uncacheable = true;
        set beresp.ttl = 120s; # 短暫快取供優雅降級
        return (deliver);
    }

    # 2. Set-Cookie 存在則不快取 (避免快取含 Session 的頁面)
    if (beresp.http.Set-Cookie) {
        set beresp.uncacheable = true;
        return (deliver);
    }

    # 3. 靜態資源長期快取 (1 年)
    if (bereq.url ~ "\.(css|js|jpg|jpeg|png|gif|ico|woff|woff2|svg|webp|mp4|pdf)(\?.*)?$") {
        set beresp.ttl = 365d;
        set beresp.http.Cache-Control = "public, max-age=31536000";
        # 移除可能干擾的 header
        unset beresp.http.ETag;
        unset beresp.http.Last-Modified;
    }

    # 4. HTML 頁面短期快取 (5 分鐘) - 視業務調整
    if (bereq.url ~ "\.html?(\?.*)?$") {
        set beresp.ttl = 300s;
        set beresp.http.Cache-Control = "public, max-age=300";
    }

    # 5. API 回應極短快取或不快取
    if (bereq.url ~ "^/api/") {
        set beresp.ttl = 10s;
        set beresp.http.Cache-Control = "public, max-age=10, stale-while-revalidate=60";
    }

    return (deliver);
}

vcl_deliver (回應客戶端前) - 加入快取命中標記

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
        set resp.http.X-Cache-Hits = obj.hits;
    } else {
        set resp.http.X-Cache = "MISS";
    }
    # 移除內部 header
    unset resp.http.Via;
    unset resp.http.X-Varnish;
}

其他子程式

# 管道模式 (非快取直通)
sub vcl_pipe {
    return (pipe);
}

# 快取未命中 -> 取得後端
sub vcl_miss {
    return (fetch);
}

# 快取命中
sub vcl_hit {
    if (obj.ttl >= 0s) {
        return (deliver);
    }
    return (miss); # 已過期
}

# 雜湊鍵值 (預設: URL + Host)
sub vcl_hash {
    hash_data(req.url);
    if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }
    # 可加入其他維度,如 Cookie、User-Agent
    # if (req.http.Cookie) { hash_data(req.http.Cookie); }
}

啟動參數與系統服務

建立專用使用者

groupadd -r varnish
useradd -r -g varnish -s /sbin/nologin -d /var/lib/varnish varnish

快取儲存配置

# 檔案型快取 (適合大容量、持久化)
# -s file,/var/lib/varnish/varnish_storage.bin,10G

# 記憶體型快取 (極速、重啟遺失)
# -s malloc,4G

systemd 服務檔 (/etc/systemd/system/varnish.service)

[Unit]
Description=Varnish HTTP Accelerator
After=network.target

[Service]
Type=forking
LimitNOFILE=100000
LimitMEMLOCK=infinity
ExecStartPre=/usr/local/varnish/sbin/varnishd -C -f /usr/local/varnish/etc/varnish/default.vcl
ExecStart=/usr/local/varnish/sbin/varnishd \
    -a :80 \
    -a :8443,PROXY \
    -f /usr/local/varnish/etc/varnish/default.vcl \
    -s malloc,4G \
    -w 500,10000,30 \
    -t 120 \
    -T 127.0.0.1:6082 \
    -u varnish -g varnish \
    -p feature=+http2 \
    -p thread_pool_min=100 \
    -p thread_pool_max=5000 \
    -p thread_pool_timeout=300 \
    -p workspace_client=64k \
    -p workspace_backend=64k

ExecReload=/usr/local/varnish/sbin/varnishd -C -f /usr/local/varnish/etc/varnish/default.vcl
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

關鍵參數說明

參數說明建議值
-a監聽位址:埠,支援 PROXY 協定:80, :8443,PROXY
-s儲存後端:malloc(記憶體) 或 file(磁碟)malloc,4G (記憶體足夠時)
-w執行緒池:min,max,timeout500,10000,30
-t預設 TTL (秒)120
-T管理介面 IP:埠127.0.0.1:6082
-p feature=+http2啟用 HTTP/2 支援必要

日誌管理與切割

varnishncsa 存取日誌

# 啟動 (背景執行)
varnishncsa -a -w /var/log/varnish/access.log -D \
    -F '%{X-Forwarded-For}i %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %D %{Varnish:hitmiss}x'

# 格式說明:
# %D = 微秒耗時
# %{Varnish:hitmiss}x = HIT/MISS 標記

每日切割腳本 (/usr/local/sbin/varnish-logrotate.sh)

#!/bin/bash
LOG_DIR="/var/log/varnish"
DATE=$(date -d "yesterday" +%Y-%m-%d)

# 發送 USR1 信號讓 varnishncsa 重新開啟日誌檔
pkill -USR1 varnishncsa

# 壓縮舊日誌
mv "$LOG_DIR/access.log" "$LOG_DIR/access-$DATE.log"
gzip "$LOG_DIR/access-$DATE.log"

# 刪除 30 天前日誌
find "$LOG_DIR" -name "access-*.log.gz" -mtime +30 -delete

logrotate 配置 (/etc/logrotate.d/varnish)

/var/log/varnish/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 640 varnish varnish
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /var/run/varnishncsa.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

Linux 核心網路參數調優 (/etc/sysctl.d/99-varnish.conf)

# TCP 連線優化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0  # NAT 環境下勿開啟
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.ip_local_port_range = 10240 65535

# 記憶體緩衝
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# 檔案描述符
fs.file-max = 1000000
fs.nr_open = 1000000
# 套用
sysctl --system

管理操作與監控

varnishadm 常用指令

# 連線管理介面
varnishadm -T 127.0.0.1:6082

# 查看後端健康狀態
backend.list

# 手動設定後端健康/病狀
backend.set_health web01 sick
backend.set_health web01 healthy

# 清除快取 (purge)
ban req.http.host == "example.com" && req.url ~ "^/images/"

# 即時統計
varnishstat

# 即時日誌 (篩選)
varnishlog -g request -q "ReqUrl ~ '/api/'"
varnishlog -g request -q "RespStatus >= 500"

關鍵統計指標 (varnishstat)

指標含義健康閾值
MAIN.client_req客戶端請求總數持續增長
MAIN.cache_hit快取命中次數Hit Rate > 80%
MAIN.cache_miss快取未命中低於 20%
MAIN.backend_fail後端連線失敗應為 0
MAIN.threads_created建立執行緒數平穩
MAIN.sess_dropped連線被拒 (滿載)應為 0
SMA.*.g_bytes記憶體快取使用量< 80% 配額

常見問題排查

現象可能原因排查步驟
命中率低Cookie 污染、VCL 不快取規則錯誤、TTL 太短檢查 vcl_recv unset Cookie、vcl_backend_response TTL 設定、varnishlog 分析 MISS 原因
後端 503後端掛掉、健康檢查失敗、連線逾時backend.list 看健康狀態、檢查後端 /healthz、調整 probe 參數
記憶體暴增malloc 過大、快取物件過大、記憶體洩漏限制 -s malloc 大小、設定 obj.ttl、升級 Varnish 版本
大檔案下載中斷between_bytes_timeout 太短調大 .between_bytes_timeout (如 300s)

總結

Varnish 優化核心在於:精準的 VCL 快取策略 (什麼快取、多久、如何失效)、健康的後端叢集 (探針、負載均衡、優雅降級)、系統層面的資源配置 (記憶體、執行緒、核心參數)、可觀測性 (日誌、統計、告警)。本文提供的配置模板可作為生產環境基準,根據實際流量與業務特性微調參數。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved