Nginx/OpenResty 反代配置最佳实践

我一开始用的是 Nginx 后来全换成了 OpenResty。原因很简单:OpenResty 就是 Nginx + Lua,灵活度不是一个量级的。

这篇讲讲我这一年多踩过的反代坑和最终稳定运行的配置。

为什么选 OpenResty

最初装 Nginx 是因为"大家都在用",后来发现几个痛点:

1. 动态 upstream 管理 — Nginx 改完配置要 nginx -s reload,高峰期 reload 会短暂影响服务。OpenResty 可以用 Lua 动态添加/删除 upstream,不 reload

2. 限流、防爬、认证 — 这些功能 Nginx 要装模块,OpenResty 内置 Lua + Redis / Memcached,随手写几行代码就能搞定

3. WAF 能力 — 简单的 CC 攻击拦截、SQL 注入检测,Lua 脚本几分钟写一个

我现在的反代层全跑在 OpenResty 上,后端 22 个容器基本都靠它转发。

基础反代配置

upstream halo_backend {

server halo:8090;

keepalive 32;

}

server {

listen 80;

server_name soulwrite.xyz;

return 301 https://$host$request_uri;

}

server {

listen 443 ssl http2;

server_name soulwrite.xyz;

ssl_certificate /etc/nginx/ssl/soulwrite.xyz.pem;

ssl_certificate_key /etc/nginx/ssl/soulwrite.xyz.key;

ssl_protocols TLSv1.2 TLSv1.3;

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;

ssl_prefer_server_ciphers off;

location / {

proxy_pass http://halo_backend;

proxy_http_version 1.1;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header Connection "";

# 解决 WebSocket 问题

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection "upgrade";

# 超时设置

proxy_connect_timeout 60s;

proxy_send_timeout 60s;

proxy_read_timeout 60s;

}

}

静态资源缓存

博客主要流量是 CSS/JS/图片,反代缓存能显著降低后端压力:

location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff2?|ttf|eot)$ {

proxy_pass http://halo_backend;

expires 30d;

add_header Cache-Control "public, immutable";

access_log off;

}

动态 Upstream(OpenResty+Lua)

有时候后端服务要重启或者迁移 IP,静态写死的 upstream 就不方便。我用 Lua 动态读取:

resolver 8.8.8.8 ipv6=off;

set_by_lua $backend '

local hosts = {

["halo"] = "halo:8090",

["alist"] = "alist:5244",

["ollama"] = "ollama:11434"

}

return hosts[ng.var.host] or "127.0.0.1:80"

';

这样改后端 IP 只需要改 Lua 代码,不用动 Nginx 配置。

踩坑记录

坑 1:WebSocket 断开

Halo 和有些服务用 WebSocket,最初没加 Upgrade 头,连接几秒就断。后来加上:

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection "upgrade";

问题解决。

坑 2:SSL 握手超时

某次加完 SSL 后部分客户端报 SSL_do_handshake() failed。查了一通发现是 TLS 版本和 Cipher 配置问题。改成上面配置里的写法,兼容性最好。

坑 3:Proxy Buffer 太小

博客文章里有大量内容时,后端响应被 OpenResty buffer 住导致超时。调大:

proxy_buffering on;

proxy_buffer_size 128k;

proxy_buffers 8 256k;

proxy_busy_buffers_size 256k;

完整配置目录结构

/opt/services/reverse-proxy/

├── docker-compose.yml

├── conf.d/

│ ├── halo.conf

│ ├── alist.conf

│ ├── ollama.conf

│ └── tools.conf

├── ssl/

│ ├── soulwrite.xyz.pem

│ └── soulwrite.xyz.key

└── nginx.conf (主配置)

总结

OpenResty 比 Nginx 灵活在哪:

- reload 零感知 — Lua 动态刷新

- 限流防爬 — 几行代码搞定

- WebSocket 原生支持

我现在 22 个服务全靠这一层反代,一个容器搞定所有转发,维护成本极低。