后端服务器 #

一、后端概述 #

1.1 什么是后端 #

后端(Backend)是Varnish转发请求的目标服务器。Varnish作为反向代理,将未命中缓存的请求转发到后端服务器。

1.2 后端架构 #

text
┌─────────────────────────────────────────────────────────┐
│                    Varnish 后端架构                       │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   Client ──► Varnish ──┬──► Backend 1 (Web Server)     │
│                         │                               │
│                         ├──► Backend 2 (API Server)     │
│                         │                               │
│                         └──► Backend 3 (Static Server)  │
│                                                         │
└─────────────────────────────────────────────────────────┘

二、基本后端配置 #

2.1 单后端配置 #

vcl
vcl 4.1;

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

2.2 后端参数详解 #

vcl
backend default {
    # 必需参数
    .host = "192.168.1.10";         # 后端主机地址
    .port = "80";                    # 后端端口
    
    # 可选参数
    .host_header = "example.com";    # 覆盖Host头
    .connect_timeout = 5s;           # 连接超时
    .first_byte_timeout = 90s;       # 首字节超时
    .between_bytes_timeout = 2s;     # 字节间超时
    .max_connections = 300;          # 最大连接数
    .proxy_header = 1;               # PROXY协议版本
    .proxy_header = 2;               # PROXY协议v2
}

2.3 参数说明 #

参数 默认值 说明
host 必需 后端主机名或IP
port 必需 后端端口
host_header 发送给后端的Host头
connect_timeout 3.5s TCP连接超时
first_byte_timeout 60s 等待首字节超时
between_bytes_timeout 60s 字节间超时
max_connections 无限制 最大并发连接数
proxy_header PROXY协议版本

2.4 域名后端 #

vcl
backend default {
    .host = "backend.example.com";
    .port = "80";
}

注意:域名只在VCL加载时解析一次,IP变化需要重新加载VCL。

三、多后端配置 #

3.1 定义多个后端 #

vcl
vcl 4.1;

# 静态资源后端
backend static {
    .host = "192.168.1.10";
    .port = "80";
}

# API后端
backend api {
    .host = "192.168.1.20";
    .port = "8080";
}

# 管理后台后端
backend admin {
    .host = "192.168.1.30";
    .port = "8080";
}

3.2 后端选择 #

vcl
sub vcl_recv {
    # 根据URL选择后端
    if (req.url ~ "^/api/") {
        set req.backend_hint = api;
    } elseif (req.url ~ "^/admin/") {
        set req.backend_hint = admin;
    } else {
        set req.backend_hint = static;
    }
}

3.3 基于Host选择 #

vcl
sub vcl_recv {
    if (req.http.Host == "api.example.com") {
        set req.backend_hint = api;
    } elseif (req.http.Host == "admin.example.com") {
        set req.backend_hint = admin;
    } else {
        set req.backend_hint = static;
    }
}

3.4 基于Header选择 #

vcl
sub vcl_recv {
    if (req.http.X-Backend == "api") {
        set req.backend_hint = api;
    } elseif (req.http.X-Backend == "admin") {
        set req.backend_hint = admin;
    }
}

四、健康检查 #

4.1 基本健康检查 #

vcl
backend default {
    .host = "192.168.1.10";
    .port = "80";
    
    .probe = {
        .url = "/healthcheck";
        .timeout = 2s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

4.2 健康检查参数 #

参数 默认值 说明
url / 检查URL
timeout 2s 超时时间
interval 5s 检查间隔
window 8 检查窗口大小
threshold 3 健康阈值
initial 0 初始延迟
expected_response 200 期望响应码

4.3 高级健康检查 #

vcl
backend default {
    .host = "192.168.1.10";
    .port = "80";
    
    .probe = {
        .request =
            "GET /healthcheck HTTP/1.1"
            "Host: example.com"
            "Connection: close"
            "User-Agent: Varnish Health Check"
            "";
        .timeout = 2s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
        .expected_response = 200;
    }
}

4.4 共享健康检查 #

vcl
probe healthcheck {
    .url = "/healthcheck";
    .timeout = 2s;
    .interval = 5s;
    .window = 5;
    .threshold = 3;
}

backend server1 {
    .host = "192.168.1.10";
    .port = "80";
    .probe = healthcheck;
}

backend server2 {
    .host = "192.168.1.11";
    .port = "80";
    .probe = healthcheck;
}

4.5 查看健康状态 #

bash
# 查看后端列表
varnishadm backend.list

# 输出示例
name      ref   probe   health
default   1     5/5     healthy
server1   1     5/5     healthy
server2   1     3/5     sick

# 详细信息
varnishadm backend.list -p

4.6 手动设置健康状态 #

bash
# 设置为健康
varnishadm backend.set_health default healthy

# 设置为不健康
varnishadm backend.set_health default sick

# 设置为自动(使用健康检查)
varnishadm backend.set_health default auto

五、动态后端 #

5.1 使用directors模块 #

vcl
import directors;

backend server1 { .host = "192.168.1.10"; .port = "80"; }
backend server2 { .host = "192.168.1.11"; .port = "80"; }
backend server3 { .host = "192.168.1.12"; .port = "80"; }

sub vcl_init {
    new cluster = directors.round_robin();
    cluster.add_backend(server1);
    cluster.add_backend(server2);
    cluster.add_backend(server3);
}

sub vcl_recv {
    set req.backend_hint = cluster.backend();
}

5.2 动态后端创建 #

Varnish 6.0+支持运行时创建后端:

vcl
import dynamic;

sub vcl_init {
    new d = dynamic.director(
        port = "8080",
        ttl = 10m
    );
}

sub vcl_recv {
    # 动态添加后端
    set req.backend_hint = d.backend("server1.example.com");
}

六、后端故障处理 #

6.1 故障转移 #

vcl
import directors;

backend primary {
    .host = "192.168.1.10";
    .port = "80";
}

backend fallback {
    .host = "192.168.1.20";
    .port = "80";
}

sub vcl_init {
    new cluster = directors.fallback();
    cluster.add_backend(primary);
    cluster.add_backend(fallback);
}

sub vcl_recv {
    set req.backend_hint = cluster.backend();
}

6.2 重试机制 #

vcl
sub vcl_backend_response {
    # 后端错误时重试
    if (beresp.status >= 500) {
        return (retry);
    }
}

sub vcl_backend_error {
    # 重试次数限制
    if (bereq.retries >= 3) {
        return (deliver);
    }
    
    # 切换到备用后端
    set bereq.backend = fallback;
    return (retry);
}

6.3 优雅降级 #

vcl
sub vcl_backend_error {
    # 返回自定义错误页面
    set beresp.status = 503;
    set beresp.http.Content-Type = "text/html";
    synthetic({"<!DOCTYPE html>
<html>
<head><title>Service Temporarily Unavailable</title></head>
<body>
<h1>Service Temporarily Unavailable</h1>
<p>The server is temporarily unavailable. Please try again later.</p>
</body>
</html>"});
    return (deliver);
}

七、后端连接管理 #

7.1 连接池 #

vcl
backend default {
    .host = "192.168.1.10";
    .port = "80";
    .max_connections = 300;
}

7.2 连接超时配置 #

vcl
backend default {
    .host = "192.168.1.10";
    .port = "80";
    .connect_timeout = 5s;
    .first_byte_timeout = 90s;
    .between_bytes_timeout = 2s;
}

7.3 全局超时参数 #

bash
# 设置全局超时
varnishadm param.set connect_timeout 5
varnishadm param.set first_byte_timeout 60
varnishadm param.set between_bytes_timeout 60

八、后端认证 #

8.1 Basic认证 #

vcl
sub vcl_backend_fetch {
    # 添加Basic认证头
    set bereq.http.Authorization = "Basic " + 
        "base64(username:password)";
}

8.2 自定义认证 #

vcl
sub vcl_backend_fetch {
    # 添加自定义认证头
    set bereq.http.X-API-Key = "your-api-key";
    set bereq.http.X-Auth-Token = "your-token";
}

九、PROXY协议 #

9.1 启用PROXY协议 #

vcl
backend default {
    .host = "192.168.1.10";
    .port = "80";
    .proxy_header = 1;  # PROXY协议v1
}

9.2 PROXY协议版本 #

版本 说明
1 文本格式
2 二进制格式

9.3 后端配置 #

Nginx配置:

nginx
server {
    listen 80 proxy_protocol;
    
    set_real_ip_from 192.168.1.0/24;
    real_ip_header proxy_protocol;
}

HAProxy配置:

text
backend servers
    server server1 192.168.1.10:80 send-proxy

十、后端监控 #

10.1 后端统计 #

bash
# 查看后端连接数
varnishstat -1 -f VBE.*

# 查看特定后端
varnishstat -1 -f VBE.default.*

# 查看健康检查
varnishstat -1 -f MAIN.backend_*

10.2 关键指标 #

指标 说明
VBE.*.conn 当前连接数
VBE.*.req 请求数
VBE.*.fail 失败次数
MAIN.backend_conn 后端连接总数
MAIN.backend_unhealthy 不健康后端数
MAIN.backend_busy 忙碌后端数

10.3 监控脚本 #

bash
#!/bin/bash
# backend_monitor.sh

echo "=== Backend Status ==="
varnishadm backend.list

echo ""
echo "=== Backend Connections ==="
varnishstat -1 -f VBE.*.conn

echo ""
echo "=== Backend Failures ==="
varnishstat -1 -f VBE.*.fail

十一、完整配置示例 #

11.1 生产环境配置 #

vcl
vcl 4.1;

import directors;
import std;

# 定义健康检查
probe healthcheck {
    .url = "/healthcheck";
    .timeout = 2s;
    .interval = 5s;
    .window = 5;
    .threshold = 3;
    .expected_response = 200;
}

# 定义后端服务器
backend web1 {
    .host = "192.168.1.10";
    .port = "80";
    .probe = healthcheck;
    .max_connections = 500;
    .connect_timeout = 5s;
    .first_byte_timeout = 90s;
    .between_bytes_timeout = 2s;
}

backend web2 {
    .host = "192.168.1.11";
    .port = "80";
    .probe = healthcheck;
    .max_connections = 500;
    .connect_timeout = 5s;
    .first_byte_timeout = 90s;
    .between_bytes_timeout = 2s;
}

backend web3 {
    .host = "192.168.1.12";
    .port = "80";
    .probe = healthcheck;
    .max_connections = 500;
    .connect_timeout = 5s;
    .first_byte_timeout = 90s;
    .between_bytes_timeout = 2s;
}

backend api1 {
    .host = "192.168.2.10";
    .port = "8080";
    .probe = healthcheck;
    .max_connections = 300;
}

backend api2 {
    .host = "192.168.2.11";
    .port = "8080";
    .probe = healthcheck;
    .max_connections = 300;
}

# 初始化负载均衡器
sub vcl_init {
    new web_cluster = directors.round_robin();
    web_cluster.add_backend(web1);
    web_cluster.add_backend(web2);
    web_cluster.add_backend(web3);
    
    new api_cluster = directors.round_robin();
    api_cluster.add_backend(api1);
    api_cluster.add_backend(api2);
}

# 请求处理
sub vcl_recv {
    # 根据URL选择后端
    if (req.url ~ "^/api/") {
        set req.backend_hint = api_cluster.backend();
    } else {
        set req.backend_hint = web_cluster.backend();
    }
    
    # 添加客户端IP
    set bereq.http.X-Forwarded-For = client.ip;
}

# 后端错误处理
sub vcl_backend_error {
    set beresp.status = 503;
    set beresp.http.Content-Type = "text/html; charset=utf-8";
    synthetic({"<!DOCTYPE html>
<html>
<head><title>Service Unavailable</title></head>
<body>
<h1>503 Service Unavailable</h1>
<p>The server is temporarily unavailable.</p>
</body>
</html>"});
    return (deliver);
}

十二、总结 #

本章我们学习了:

  1. 后端概述:后端概念和架构
  2. 基本配置:单后端、参数详解
  3. 多后端:定义和选择策略
  4. 健康检查:配置和监控
  5. 动态后端:运行时创建
  6. 故障处理:故障转移、重试、降级
  7. 连接管理:连接池、超时配置
  8. 后端认证:Basic认证、自定义认证
  9. PROXY协议:传递客户端信息
  10. 后端监控:统计和监控脚本

掌握后端配置后,让我们进入下一章,学习负载均衡!

最后更新:2026-03-28