VictoriaMetrics在时序数据库领域以高压缩比和低内存占用著称,单实例通常就能扛住每秒数十万条写入。但真实生产环境很少会让业务系统直连数据库,原因有三:直连会让VictoriaMetrics直接承受所有客户端连接,容易触发文件描述符上限;每次新建连接都要重复TLS握手;当上游有多个VictoriaMetrics实例时,客户端难以实现均匀的负载分配。此时在VictoriaMetrics前面放置一层Nginx,可以低成本解决这些问题。

一、代理层为什么能降低延迟并提升稳定性
VictoriaMetrics本身基于Go语言开发,并发处理能力不弱,但Go的调度模型在面对海量短连接时仍然会产生不小的开销。每一条TCP连接都需要文件描述符和内存缓冲,一旦连接数超过内核限制或进程的ulimit配置,写入和查询就会直接失败。Nginx采用事件驱动架构,单个worker进程就能维护数万条空闲连接,配合upstream keepalive机制,可以将大量客户端请求收敛到少量与后端VictoriaMetrics之间的长连接上。这样后端不需要频繁接受新连接,也减少了TIME_WAIT状态堆积。
另一个容易被忽视的点是TLS卸载。虽然VictoriaMetrics原生支持HTTPS,但Go标准库的TLS实现针对通用场景,性能通常不如Nginx配合OpenSSL或BoringSSL的优化。把证书放在Nginx这一层进行终结,后端走内网HTTP明文通信,既能降低VictoriaMetrics的CPU占用,又能统一管理证书续期和协议版本。对于查询延迟敏感的场景,TLS握手节省下来的几十毫秒会直接反映在P99指标上。
Nginx还提供了请求体大小限制、URL访问控制、限速等安全能力。VictoriaMetrics的写入端点如果没有任何保护,任意客户端都能灌入垃圾数据。通过Nginx配置client_max_body_size和limit_req,可以在入口处拦截异常流量,避免数据库被大请求体或突发查询拖垮。这些功能不需要改动VictoriaMetrics本身,符合关注点分离的运维原则。
二、Nginx反向代理VictoriaMetrics核心配置
先给出一个可以直接用于单机版VictoriaMetrics的反向代理配置。单机版默认监听8480端口提供写入和查询API,Nginx把这些路径转发到后端即可。为了连接复用,必须显式设置HTTP协议版本并清空Connection头,否则Nginx默认会发送Connection: close,导致每次请求都新建后端连接,keepalive参数形同虚设。
upstream victoriametrics {
server 127.0.0.1:8480 max_fails=3 fail_timeout=10s;
keepalive 32;
}
server {
listen 80;
server_name metrics.ipipp.com;
location /api/v1/write {
proxy_pass http://victoriametrics;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
client_max_body_size 64m;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
location /api/v1/query {
proxy_pass http://victoriametrics;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 64k;
}
location /api/v1/query_range {
proxy_pass http://victoriametrics;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 64k;
}
}
上面的配置中,<location>块分别对写入和查询做了不同的超时设置。写入请求的body可能较大,client_max_body_size设置为64m可以满足绝大多数Prometheus远程写入场景。查询请求则启用了proxy_buffering,这样Nginx会先把后端响应缓冲到内存或磁盘,再统一返回给客户端,避免慢客户端阻塞后端连接。
proxy_set_header Connection ""这一行是关键。如果不设置,Nginx会向后端发送Connection: close,keepalive机制就不会生效。设置成空值后,Nginx不再追加Connection头,后端VictoriaMetrics会按照HTTP/1.1默认行为保持连接。配合upstream块中的keepalive 32,可以维持32条到后端的空闲长连接,足以承载每秒数万次请求的复用。
三、集群模式下的负载均衡与故障转移
当单实例VictoriaMetrics无法满足容量需求时,通常会切换到集群模式。集群由vminsert负责写入,vmselect负责查询,两者可以独立扩容。Nginx需要分别定义两组上游:写入流量转发到所有vminsert节点,查询流量转发到所有vmselect节点。这种分离设计可以让写入和查询互相不干扰,也便于针对性地设置负载均衡策略。
upstream vminsert_servers {
server 192.168.10.21:8480 max_fails=3 fail_timeout=10s;
server 192.168.10.22:8480 max_fails=3 fail_timeout=10s;
keepalive 64;
}
upstream vmselect_servers {
server 192.168.10.23:8481 max_fails=3 fail_timeout=10s;
server 192.168.10.24:8481 max_fails=3 fail_timeout=10s;
keepalive 64;
}
server {
listen 443 ssl http2;
server_name metrics.ipipp.com;
ssl_certificate /etc/nginx/certs/metrics.crt;
ssl_certificate_key /etc/nginx/certs/metrics.key;
location /api/v1/write {
proxy_pass http://vminsert_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
client_max_body_size 64m;
}
location /api/v1/query {
proxy_pass http://vmselect_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_read_timeout 60s;
}
location /api/v1/query_range {
proxy_pass http://vmselect_servers;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_read_timeout 120s;
}
}
健康检查通过max_fails和fail_timeout实现。例如max_fails=3表示在fail_timeout时间内连续失败3次后,该节点会被标记为不可用,Nginx将请求转发给其他健康节点。VictoriaMetrics集群中的某个vmselect即使挂掉,只要还有存活节点,查询就不会中断。对于写入链路,vminsert节点本身无状态,任意一台都能处理写入请求,因此负载均衡的收益非常明显。
需要注意的是,集群模式下查询路径可能包含cluster参数,用于在多个vmstorage之间做全局查询。Nginx不需要理解这些参数,只需原样转发即可。但建议保持proxy_pass不带URI部分,这样原始请求路径可以完整透传,避免因为前缀替换导致VictoriaMetrics返回404。
四、压测数据与参数调优对比
为了验证代理层的实际收益,用avalanche生成模拟时序数据,通过Nginx代理和直连两种方式写入VictoriaMetrics。环境为4核8G虚拟机,VictoriaMetrics单实例部署,Nginx使用4个worker进程,worker_connections设为4096,upstream keepalive设为64。写入速率约为每秒10万条样本,每条样本包含10个标签。测试持续10分钟,观察P99延迟和连接数变化。
直连模式下,VictoriaMetrics自身平均写入延迟约15ms,但P99达到220ms,因为大量客户端同时建立连接触发了Go调度器的频繁切换。通过Nginx代理后,平均延迟略升至17ms,但P99下降到95ms,连接数从直连时的8000多条降到Nginx与后端之间的64条长连接。查询端用wrk对/api/v1/query_range进行压测,代理后的吞吐提升约35%,主要原因是连接复用消除了三次握手和TLS握手开销。
压测过程中也发现一个容易踩的坑:当并发连接数超过worker_connections与worker_processes的乘积时,Nginx会拒绝新连接,而直接调整这两个参数还不够,必须同步修改系统的worker_rlimit_nofile和net.core.somaxconn。否则Nginx虽然配置了更大的连接数,但进程能打开的文件描述符数量仍然受限,压测时会看到大量too many open files错误。另一个建议是开启keepalive_timeout 60s,让空闲连接在合理时间内释放,避免后端维持过多无活动连接。
实际部署时,如果发现查询延迟抖动,可以检查proxy_buffering是否开启,并适当增大proxy_buffer_size。对于响应体较大的范围查询,缓冲可以把数据完整读入Nginx内存后再响应,减少后端进程被慢客户端拖住的时间。结合Nginx自带的stub_status模块暴露活跃连接数,也能帮助判断是否需要进一步扩容后端节点。
NginxVictoriaMetrics时序数据修改时间:2026-09-30 23:48:14