VMOD扩展 #
一、VMOD概述 #
1.1 什么是VMOD #
VMOD (Varnish Module) 是Varnish的扩展模块系统,允许使用C语言编写扩展功能,为VCL提供额外的函数和能力。
1.2 VMOD优势 #
| 优势 | 说明 |
|---|---|
| 高性能 | C语言实现,性能优异 |
| 可扩展 | 添加VCL不具备的功能 |
| 模块化 | 按需加载,灵活配置 |
| 社区支持 | 丰富的第三方模块 |
二、安装VMOD #
2.1 安装varnish-modules #
bash
# Ubuntu/Debian
sudo apt install varnish-modules
# CentOS/RHEL
sudo yum install varnish-modules
# Fedora
sudo dnf install varnish-modules
2.2 编译安装 #
bash
# 安装依赖
sudo apt install varnish-dev python3-docutils
# 克隆仓库
git clone https://github.com/varnish/varnish-modules.git
cd varnish-modules
# 编译安装
./configure
make
sudo make install
2.3 验证安装 #
bash
# 查看已安装的VMOD
ls /usr/lib/varnish/vmods/
# 输出示例
libvmod_bodyaccess.so
libvmod_cookie.so
libvmod_header.so
libvmod_saintmode.so
libvmod_std.so
libvmod_tcp.so
libvmod_unix.so
libvmod_vsthrottle.so
三、常用VMOD模块 #
3.1 std模块 #
vcl
import std;
sub vcl_recv {
# 时间戳
std.timestamp("request_start");
# 日志
std.log("Processing request: " + req.url);
# syslog
std.syslog(6, "Info: " + req.url);
# 字符串转换
set req.http.X-Lower = std.tolower(req.http.Host);
set req.http.X-Upper = std.toupper(req.http.Host);
# 类型转换
set req.http.X-Int = std.integer(req.http.X-Value, 0);
set req.http.X-Duration = std.duration(req.http.X-TTL, 60s);
# 健康检查
if (std.healthy(req.backend_hint)) {
# 后端健康
}
# 回滚
std.rollback(req);
# 收集头
std.collect(req.http.Cookie);
}
3.2 cookie模块 #
vcl
import cookie;
sub vcl_recv {
# 解析Cookie
cookie.parse(req.http.Cookie);
# 获取Cookie值
set req.http.X-Session = cookie.get("session_id");
# 设置Cookie
cookie.set("visited", "true");
# 删除Cookie
cookie.delete("tracking_id");
# 重新构建Cookie字符串
set req.http.Cookie = cookie.get_string();
}
3.3 header模块 #
vcl
import header;
sub vcl_deliver {
# 添加头
header.append(resp.http.X-Forwarded-For, client.ip);
# 复制头
header.copy(resp.http.X-Original-Host, req.http.Host);
# 删除头
header.unset(resp.http.X-Powered-By);
# 正则替换
header.regsub(resp.http.Server, "Apache", "MyServer");
}
3.4 vsthrottle模块 #
vcl
import vsthrottle;
sub vcl_recv {
# 限流
if (vsthrottle.is_denied("ip_" + client.ip, 100, 1s)) {
return (synth(429, "Too Many Requests"));
}
}
3.5 bodyaccess模块 #
vcl
import bodyaccess;
sub vcl_recv {
# 限制请求体大小
if (req.method == "POST") {
if (req.http.Content-Length > 1048576) {
return (synth(413, "Payload Too Large"));
}
}
}
3.6 tcp模块 #
vcl
import tcp;
sub vcl_recv {
# 设置TCP选项
tcp.set_socket_pace(1000);
# 获取连接信息
set req.http.X-Local-Port = tcp.local_port();
}
3.7 unix模块 #
vcl
import unix;
sub vcl_init {
# 使用Unix socket连接后端
new u = unix.socket("/var/run/backend.sock");
}
3.8 saintmode模块 #
vcl
import saintmode;
sub vcl_init {
# 创建带熔断的后端
new sm = saintmode.saintmode(backend1, 5);
}
sub vcl_recv {
set req.backend_hint = sm.backend();
}
四、第三方VMOD #
4.1 vmod-dynamic #
动态后端管理:
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");
}
4.2 vmod-geoip #
地理位置识别:
vcl
import geoip;
sub vcl_recv {
# 获取国家代码
set req.http.X-Country = geoip.country_code(client.ip);
# 获取城市
set req.http.X-City = geoip.city(client.ip);
# 地理路由
if (geoip.country_code(client.ip) == "CN") {
set req.backend_hint = china_backend;
}
}
4.3 vmod-curl #
HTTP客户端:
vcl
import curl;
sub vcl_recv {
# 发送HTTP请求
new req = curl.request("GET", "http://api.example.com/check");
req.set_header("Authorization", "Bearer token");
if (req.perform() == 0) {
set req.http.X-Check-Result = req.get_body();
}
}
4.4 vmod-redis #
Redis集成:
vcl
import redis;
sub vcl_init {
new r = redis.client("127.0.0.1", 6379);
}
sub vcl_recv {
# 获取缓存
set req.http.X-Cache-Key = r.get("cache_key:" + req.url);
# 设置缓存
r.set("cache_key:" + req.url, "value", 3600);
}
4.5 vmod-jwt #
JWT处理:
vcl
import jwt;
sub vcl_recv {
# 验证JWT
if (req.http.Authorization ~ "Bearer ") {
set req.http.X-Token = regsub(req.http.Authorization, "^Bearer ", "");
if (jwt.verify(req.http.X-Token, "secret-key")) {
set req.http.X-User-ID = jwt.get_claim("user_id");
} else {
return (synth(401, "Invalid Token"));
}
}
}
五、自定义VMOD开发 #
5.1 VMOD结构 #
text
vmod_example/
├── src/
│ ├── vmod_example.c # 源代码
│ └── vmod_example.vcc # VCL接口定义
├── autogen.sh
├── configure.ac
└── Makefile.am
5.2 VCC接口定义 #
c
# vmod_example.vcc
$Module example 3 "Example VMOD"
$Function STR hello(STRING name)
$Function INT add(INT a, INT b)
$Function VOID log(STRING message)
5.3 C实现 #
c
// vmod_example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vmod_example.h"
VCL_STRING vmod_hello(VRT_CTX, VCL_STRING name) {
char *result;
size_t len;
if (name == NULL) {
name = "World";
}
len = strlen("Hello, ") + strlen(name) + strlen("!");
result = malloc(len + 1);
snprintf(result, len + 1, "Hello, %s!", name);
return result;
}
VCL_INT vmod_add(VRT_CTX, VCL_INT a, VCL_INT b) {
return a + b;
}
VCL_VOID vmod_log(VRT_CTX, VCL_STRING message) {
if (message != NULL) {
VSL(ctx->vsl, SLT_VCL_Log, "%s", message);
}
}
5.4 编译安装 #
bash
# 生成配置脚本
./autogen.sh
# 配置
./configure VARNISHSRC=/path/to/varnish/source
# 编译
make
# 安装
sudo make install
5.5 使用自定义VMOD #
vcl
import example;
sub vcl_recv {
# 调用自定义函数
set req.http.X-Greeting = example.hello("Varnish");
# 计算函数
set req.http.X-Sum = example.add(10, 20);
# 日志函数
example.log("Processing request");
}
六、VMOD最佳实践 #
6.1 性能考虑 #
c
// 避免频繁内存分配
// 使用工作区内存
VCL_STRING vmod_example(VRT_CTX, VCL_STRING input) {
// 使用Varnish工作区内存
char *result = WS_Printf(ctx->ws, "Result: %s", input);
return result;
}
6.2 错误处理 #
c
VCL_STRING vmod_safe_operation(VRT_CTX, VCL_STRING input) {
if (input == NULL) {
VSL(ctx->vsl, SLT_VCL_Error, "Input is NULL");
return NULL;
}
// 安全操作
return result;
}
6.3 线程安全 #
c
// 使用线程局部存储或互斥锁
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
VCL_VOID vmod_thread_safe(VRT_CTX) {
pthread_mutex_lock(&lock);
// 临界区操作
pthread_mutex_unlock(&lock);
}
七、VMOD调试 #
7.1 启用调试 #
bash
# 启动Varnish调试模式
varnishd -d -f /etc/varnish/default.vcl
# 查看VMOD加载日志
varnishlog -q "VCL_Log"
7.2 测试VMOD #
bash
# 使用varnishtest
varnishtest test.vtc
测试脚本示例:
vtc
# test.vtc
varnish v1 -vcl {
import example;
backend default { .host = "127.0.0.1"; }
sub vcl_recv {
set req.http.X-Test = example.hello("Test");
}
} -start
client c1 {
txreq
rxresp
expect resp.http.X-Test == "Hello, Test!"
} -run
八、常用VMOD列表 #
| VMOD | 功能 | 来源 |
|---|---|---|
| std | 标准工具函数 | 官方 |
| cookie | Cookie处理 | varnish-modules |
| header | 头操作 | varnish-modules |
| vsthrottle | 限流 | varnish-modules |
| bodyaccess | 请求体访问 | varnish-modules |
| dynamic | 动态后端 | 第三方 |
| geoip | 地理位置识别 | 第三方 |
| redis | Redis集成 | 第三方 |
| jwt | JWT处理 | 第三方 |
| curl | HTTP客户端 | 第三方 |
九、总结 #
本章我们学习了:
- VMOD概述:概念、优势
- 安装VMOD:包管理器、编译安装
- 常用模块:std、cookie、header、vsthrottle
- 第三方VMOD:dynamic、geoip、redis、jwt
- 自定义开发:VCC定义、C实现、编译安装
- 最佳实践:性能、错误处理、线程安全
- 调试测试:调试模式、varnishtest
掌握VMOD扩展后,让我们进入下一章,学习日志分析!
最后更新:2026-03-28