后端服务器 #
一、后端概述 #
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);
}
十二、总结 #
本章我们学习了:
- 后端概述:后端概念和架构
- 基本配置:单后端、参数详解
- 多后端:定义和选择策略
- 健康检查:配置和监控
- 动态后端:运行时创建
- 故障处理:故障转移、重试、降级
- 连接管理:连接池、超时配置
- 后端认证:Basic认证、自定义认证
- PROXY协议:传递客户端信息
- 后端监控:统计和监控脚本
掌握后端配置后,让我们进入下一章,学习负载均衡!
最后更新:2026-03-28