Files

64 lines
2.3 KiB
Plaintext

# 网关示例:静态前端 + /api 反向代理 + /ai/stream SSE 流式代理 + 限流 + 按 Cookie 灰度
# 运行 test_gateway.py 时会把 {{...}} 占位符替换成临时端口和目录
worker_processes 1;
error_log {{PREFIX}}/error.log warn;
pid {{PREFIX}}/nginx.pid;
events { worker_connections 256; }
http {
access_log off;
# 非 root 运行时,把临时文件目录放到可写位置
client_body_temp_path {{PREFIX}}/client_body;
proxy_temp_path {{PREFIX}}/proxy;
fastcgi_temp_path {{PREFIX}}/fastcgi;
uwsgi_temp_path {{PREFIX}}/uwsgi;
scgi_temp_path {{PREFIX}}/scgi;
# 每个 IP 每秒 5 个请求,突发最多 5 个
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
limit_req_status 429;
upstream api_stable { server 127.0.0.1:{{STABLE_PORT}}; keepalive 16; }
upstream api_canary { server 127.0.0.1:{{CANARY_PORT}}; keepalive 16; }
# Cookie canary=1 的用户走新版本,其余走稳定版本
map $cookie_canary $api_backend {
default api_stable;
"1" api_canary;
}
server {
listen 127.0.0.1:{{LISTEN_PORT}};
# 前端单页应用:找不到文件时回退到 index.html,交给前端路由
location / {
root {{PREFIX}}/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
limit_req zone=api_limit burst=5 nodelay;
proxy_pass http://$api_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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_connect_timeout 3s;
proxy_read_timeout 30s;
}
# 大模型流式输出(SSE):关闭缓冲,否则 Nginx 攒满缓冲区才发给浏览器
location /ai/stream {
proxy_pass http://api_stable;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s; # 生成时间长,读超时要放宽
add_header X-Accel-Buffering no;
}
}
}