Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Varnish Cache 部署實戰:高性能 HTTP 加速器安裝、配置、VCL 編寫與運維指南

編輯:Linux 教學

Varnish 定位:記憶體級 HTTP 反向代理緩存

核心差異:

  • Nginx proxy_cache:硬碟緩存 + OS Page Cache,容量大、持久化、成本低。
  • Varnish:純記憶體緩存(malloc 或檔案映射),極致低延遲、高吞吐,適合熱門、小對象、高頻訪問的靜態/半動態內容。

架構模式:

  1. Nginx (SSL/終結/WAF) → Varnish (緩存) → 應用伺服器(推薦,職責分離)。
  2. Varnish (SSL/緩存/負載) → 應用伺服器(簡化架構,但 SSL 效能弱於 Nginx)。

一、安裝部署(原始碼編譯,生產級參數)

# 1. 依賴
yum install -y gcc make autoconf automake libtool pkgconfig \
               python3-docutils libedit-devel ncurses-devel \
               pcre2-devel jemalloc-devel   # jemalloc 提升記憶體分配效能

# 2. 下載穩定版(Varnish 7.2 LTS / 7.4 穩定版)
wget https://varnish-cache.org/_downloads/varnish-7.4.2.tgz
tar -xzf varnish-7.4.2.tgz
cd varnish-7.4.2

# 3. 配置編譯
./configure --prefix=/usr/local/varnish \
            --enable-jemalloc \
            --with-pcre2

# 4. 編譯安裝
make -j$(nproc)
make install

# 5. 用戶、目錄、權限
useradd -r -s /bin/false -d /var/lib/varnish varnish
mkdir -p /var/lib/varnish /var/log/varnish
chown -R varnish:varnish /var/lib/varnish /var/log/varnish

二、systemd 服務單元 /etc/systemd/system/varnish.service

[Unit]
Description=Varnish HTTP Accelerator
After=network.target
Documentation=man:varnishd(1)

[Service]
Type=simple
User=varnish
Group=varnish
LimitNOFILE=500000
LimitMEMLOCK=infinity
# 關鍵啟動參數
ExecStart=/usr/local/varnish/sbin/varnishd \
    -a :80 \                    # 監聽埠
    -f /usr/local/varnish/etc/varnish/default.vcl \  # VCL 配置
    -s malloc,4G \              # 儲存後端:記憶體 4GB(視機器記憶體 50-70%)
    -p thread_pools=4 \         # 線程池數(CPU 核心數)
    -p thread_pool_min=100 \    # 每池最小線程
    -p thread_pool_max=5000 \   # 每池最大線程
    -p thread_pool_timeout=300 \ # 線程閒置超時
    -p workspace_client=64k \   # 客戶端工作空間
    -p workspace_backend=64k \  # 後端工作空間
    -p http_max_hdr=128 \       # 最大頭部數
    -p http_req_hdr_len=8k \    # 請求頭最大長度
    -p http_resp_hdr_len=8k \   # 回應頭最大長度
    -T 127.0.0.1:6082 \         # 管理介面
    -S /usr/local/varnish/etc/varnish/secret        # 管理認證
ExecReload=/usr/local/varnish/bin/varnishreload -q
ExecStop=/usr/local/varnish/bin/varnishd -T 127.0.0.1:6082 -S /usr/local/varnish/etc/varnish/secret stop
PrivateTmp=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target

三、VCL (Varnish Configuration Language) 核心配置

# /usr/local/varnish/etc/varnish/default.vcl
vcl 4.1;

# ===== 後端定義 =====
backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .connect_timeout = 2s;
    .first_byte_timeout = 10s;
    .between_bytes_timeout = 5s;
    .max_connections = 1000;
    .probe = {
        .url = "/health";
        .interval = 10s;
        .timeout = 3s;
        .window = 5;
        .threshold = 3;
    }
}

# 多後端負載均衡(導演)
backend web01 { .host = "10.0.1.10"; .port = "80"; .probe = { .url = "/health"; } }
backend web02 { .host = "10.0.1.11"; .port = "80"; .probe = { .url = "/health"; } }

director web_cluster random {
    { .backend = web01; .weight = 3; }
    { .backend = web02; .weight = 2; }
}

# ===== ACL:允許 PURGE 的 IP =====
acl purge {
    "localhost";
    "127.0.0.1";
    "10.0.0.0/8";
    "192.168.0.0/16";
}

# ===== 子程序:接收請求 =====
sub vcl_recv {
    # 正規化 Host
    set req.http.Host = regsub(req.http.Host, ":.*$", "");

    # 僅緩存 GET/HEAD
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

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

    # 移除干擾緩存的頭部
    unset req.http.Cookie;           # 靜態資源無需 Cookie
    unset req.http.Authorization;    # 非認證介面移除
    # 保留特定 Cookie(如會話標識)需條件判斷

    # 正規化 Accept-Encoding
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|webp|woff2?)$") {
            unset req.http.Accept-Encoding;  # 已壓縮文件不再壓縮
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            unset req.http.Accept-Encoding;
        }
    }

    # 大文件/串流不緩存
    if (req.url ~ "\.(mp4|webm|mkv|iso|tar\.gz|zip|exe)$") {
        return (pass);
    }

    # 指定後端
    if (req.http.Host ~ "^(www|static)\.example\.com$") {
        set req.backend_hint = web_cluster;
    } else {
        set req.backend_hint = default;
    }

    return (hash);
}

# ===== 子程序:緩存鍵計算 =====
sub vcl_hash {
    hash_data(req.url);
    if (req.http.Host) {
        hash_data(req.http.Host);
    } else {
        hash_data(server.ip);
    }
    # 可選:按 Cookie 分桶(個性化內容)
    # if (req.http.Cookie) { hash_data(req.http.Cookie); }
    return (lookup);
}

# ===== 子程序:命中處理 =====
sub vcl_hit {
    if (obj.ttl >= 0s) {
        return (deliver);
    }
    if (req.http.If-None-Match || req.http.If-Modified-Since) {
        return (deliver);  # 客戶端條件請求,直接交付 304
    }
    return (fetch);  # 過期但無條件請求,回源驗證
}

# ===== 子程序:未命中/回源 =====
sub vcl_miss {
    return (fetch);
}

# ===== 子程序:後端回應處理 =====
sub vcl_backend_response {
    # 設定緩存 TTL(優先級:beresp.ttl > Cache-Control > 預設 120s)
    if (beresp.http.Cache-Control ~ "max-age") {
        # Varnish 自動解析 max-age,無需手動設定
    } else {
        set beresp.ttl = 1h;  # 兜底預設
    }

    # 靜態資源長期緩存
    if (bereq.url ~ "\.(css|js|jpg|jpeg|png|gif|ico|woff2?|svg|webp)$") {
        set beresp.ttl = 30d;
        set beresp.grace = 1h;  # 過期後仍可服務 1 小時(背景更新)
        unset beresp.http.Set-Cookie;  # 靜態資源不下發 Cookie
    }

    # HTML/動態頁面短緩存
    if (bereq.url ~ "\.(html|htm|json|xml)$") {
        set beresp.ttl = 5m;
        set beresp.grace = 10m;
    }

    # 移除後端干擾頭部
    unset beresp.http.Server;
    unset beresp.http.X-Powered-By;

    # 支援 ESI(邊緣側包含)
    if (bereq.url ~ "\.html$") {
        set beresp.do_esi = true;
    }

    return (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";
    }
    # 移除內部頭部
    unset resp.http.Via;
    unset resp.http.X-Varnish;
    unset resp.http.Age;  # 可選保留
    return (deliver);
}

# ===== 子程序:PURGE 處理 =====
sub vcl_purge {
    return (synth(200, "Purged"));
}

# ===== 子程序:錯誤頁面合成 =====
sub vcl_synth {
    if (resp.status == 405 || resp.status == 403) {
        set resp.http.Content-Type = "text/plain; charset=utf-8";
        synthetic("Access Denied");
        return (deliver);
    }
    if (resp.status >= 500 && resp.status < 600) {
        set resp.http.Content-Type = "text/html; charset=utf-8";
        synthetic({"

Service Unavailable

Backend error: " + resp.reason + "

"}); return (deliver); } }

四、日誌與監控

1. 存取日誌(NCSA 格式,支援自定義)

# 啟動時指定
varnishncsa -a -w /var/log/varnish/access.log \
    -D -P /var/run/varnishncsa.pid \
    -F '%{X-Forwarded-For}i %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %{Varnish:handling}x %{Varnish:time_firstbyte}x'

# systemd 啟動腳本整合
ExecStartPost=/usr/local/varnish/bin/varnishncsa -a -w /var/log/varnish/access.log -D -P /var/run/varnishncsa.pid

2. 即時統計工具

  • varnishstat:關鍵指標 MAIN.cache_hit, MAIN.cache_miss, MAIN.sess_conn, MAIN.threads, SMA.*.g_bytes (記憶體用量)。
  • varnishtop:即時 Top URL、Client IP、Backend 等。
  • varnishlog:詳細請求日誌(調試用),-g request -q "ReqUrl ~ '/api/'"。

3. Prometheus 整合

# 部署 varnish_exporter
wget https://github.com/jonnenauha/varnish_exporter/releases/download/v1.6.0/varnish_exporter_linux_amd64.tar.gz
./varnish_exporter --varnish.secret-file=/usr/local/varnish/etc/varnish/secret --web.listen-address=:9131

# 告警規則
- alert: VarnishHitRateLow
  expr: rate(varnish_cache_hit[5m]) / (rate(varnish_cache_hit[5m]) + rate(varnish_cache_miss[5m])) < 0.9
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Varnish 命中率低於 90%"

五、常見問題與調優

問題原因解決
記憶體用量超限、OOM Killer 殺進程-s malloc,4G 超過物理記憶體、未限制 thread_pool_max記憶體 50-70% 給 Varnish,預留給 OS Page Cache/其他進程;限制線程池上限
命中率低Cookie 干擾、Vary 過度、後端無 Cache-Control、PURGE 未生效vcl_recv 移除無關 Cookie、vcl_hash 精準鍵、後端輸出標準頭、檢查 PURGE ACL
後端健康檢查失敗、節點被踢探針 URL 回應慢/錯、閾值過嚴專用 /health 輕量端點、調整 .window/.threshold
大文件下載緩存導致記憶體暴增未在 vcl_recv pass 大文件副檔名/Content-Length 判斷 return (pass)
HTTPS 終結效能差Varnish SSL 代碼路徑未優化前置 Nginx 終結 SSL,Varnish 走 HTTP

六、平滑升級與配置熱載

# 1. 修改 VCL
vi /usr/local/varnish/etc/varnish/default.vcl

# 2. 語法檢查
/usr/local/varnish/sbin/varnishd -C -f /usr/local/varnish/etc/varnish/default.vcl

# 3. 熱載入(不重啟進程,零連接中斷)
/usr/local/varnish/bin/varnishreload -q
# 或手動
varnishadm -T 127.0.0.1:6082 -S /usr/local/varnish/etc/varnish/secret vcl.load new1 /usr/local/varnish/etc/varnish/default.vcl
varnishadm -T 127.0.0.1:6082 -S /usr/local/varnish/etc/varnish/secret vcl.use new1

總結

Varnish 作為記憶體級 HTTP 加速器,在熱門小對象、極致低延遲、高吞吐場景無可替代。核心在於:合理規劃記憶體(-s malloc)、精準 VCL(vcl_recv/vcl_hash/vcl_backend_response)、健康檢查與優雅降級、PURGE API 整合發布流程、Prometheus 監控告警。配合 Nginx 前置終結 SSL/WAF,構建「Nginx (Edge) → Varnish (Memory Cache) → App」三層架構,可將 95%+ 請求在微秒級完成,後端負載降低數量級。

Copyright © Windows教程網 All Rights Reserved