Nginx 反向代理 Spring Boot:我踩过几次 502、超时和大文件上传后整理的配置
我第一次把 Nginx 放到 Spring Boot 前面时,最先碰到的不是性能问题,而是一些看起来很小、但一上线就很烦的毛病:502、超时、上传失败、静态资源偶尔出错、日志里全是上游连接异常。很多人把反向代理理解成“前面加一层 Nginx 就完事了”,真上手才会发现,配置顺序、超时设置、Header 转发、上传限制,这些东西缺一个都可能出问题。
这篇文章不打算从“什么是 Nginx”讲起,直接讲实战。目标也很明确:让 Spring Boot 跑在 Nginx 后面时,页面能正常访问、接口不容易超时、大文件上传能过、真实客户端 IP 能拿到,遇到问题时也知道该先看哪一层。
一、先说结论:Nginx 不是摆设,是边界
把 Nginx 放在前面,最直接的好处有三个:一是做统一入口,二是接管静态资源和 HTTPS,三是把后端服务从外网直接暴露的状态里拉回来。说白了,Nginx 不是单纯“转发请求”的工具,它更像一个门卫:先看流量怎么进来,再决定哪些请求放给 Spring Boot,哪些请求直接在前面就处理掉。
如果你一开始就把责任全推给 Spring Boot,后面会很痛。比如静态文件明明能由 Nginx 直接返回,却硬要打到后端;再比如前端上传一个 20MB 文件,Nginx 默认限制不够,直接 413;或者用户访问日志里全是 127.0.0.1,真实客户端 IP 丢了,排查起来很麻烦。
二、最常见的一套基础配置
先上一个比较稳的基础版。你不用一次性把所有功能都塞进去,先让核心链路跑通,再逐项补强,通常更省事。
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host ;
proxy_set_header X-Real-IP ;
proxy_set_header X-Forwarded-For ;
proxy_set_header X-Forwarded-Proto ;
}
}
这几行里,最关键的是 proxy_set_header。很多“看起来能访问,但日志不对”的问题,根子都在这里。
Host:把原始域名传给后端,避免 Spring Boot 看到的是内部地址。X-Real-IP:把直连客户端 IP 带过去。X-Forwarded-For:保留完整代理链,排查时很有用。X-Forwarded-Proto:告诉后端当前是 http 还是 https,做跳转和生成链接时很重要。
三、502 大多不是“挂了”,而是超时或连接方式不对
很多人一看到 502 就下意识以为后端服务崩了。其实不一定。更常见的是三种情况:后端没起来、Nginx 连不上、或者 Nginx 等得不耐烦了。
先看 Nginx 日志,再看 Spring Boot 日志,这个顺序别反。因为 Nginx 先感知到失败,它会留下更直观的错误,比如 connect() failed、upstream timed out、no live upstreams 之类的信息。后端日志则更像“事情发生前后”的补充材料。
我一般会优先检查这几个点:
- Spring Boot 是否真的监听在 8080 或其他端口上。
- Nginx 的
proxy_pass是否写对了协议和端口。 - 防火墙和安全组有没有拦截本机或内网访问。
- 接口是不是本身太慢,导致代理层超时。
超时配置别太保守
Spring Boot 后面如果有数据库查询、远程接口调用、导出文件这种慢操作,默认超时往往不够。Nginx 可以适当加长:
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
send_timeout 60s;
}
这几个超时不要乱加到特别大。大不是好事,太大了,真卡住的时候用户会等很久。我的习惯是:先把链路跑通,再根据接口类型单独设置。查询类接口和导出类接口,不该用同一个超时值。
四、大文件上传:413 和空白上传页通常是 Nginx 先拦了
Spring Boot 的上传接口本身没问题,但 Nginx 默认的请求体大小限制可能先把你挡住。最常见的表现就是前端一直转圈,或者直接报 413 Request Entity Too Large。
这个时候别先怀疑后端。先把 Nginx 的限制打开:
server {
client_max_body_size 50m;
location /upload/ {
proxy_pass http://127.0.0.1:8080;
proxy_request_buffering off;
proxy_read_timeout 120s;
}
}
client_max_body_size 是第一道门。proxy_request_buffering off 则在某些上传场景里很有用,尤其是你想让请求尽快流向后端处理时。至于具体要不要关缓冲,得看业务类型,不是所有场景都适合。
如果你后台有图片、视频、导入文件这些功能,建议把上传接口单独拆个 location,别跟普通 API 混在一起。上传和查询本来就是两种流量,不能按一个模板配到底。
五、真实客户端 IP 一定要保住
这个问题看起来不大,但一旦你做审计、风控、限流、登录保护,就会非常在意。Spring Boot 如果直接拿到的是 Nginx 的内网地址,很多记录就失真了。
前面 Nginx 已经传了 X-Forwarded-For,后端也要正确识别它。Spring Boot 如果用了 Tomcat,可以考虑加上对转发头的支持;如果是 Spring Security、审计日志、接口限流,也要确认读取的是转发后的真实 IP,不是默认的 request.getRemoteAddr()。
这一步常常被忽略。等你哪天发现某个账号异常登录,全都记录成 127.0.0.1 或者内网地址,才会意识到之前少做了什么。
六、HTTPS 放在 Nginx 上更省心
证书、加密、重定向这些事,放在 Nginx 上一般更清楚。后端只管业务,外层负责 HTTPS 终止,这样 Spring Boot 的配置会干净很多。
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/cert/fullchain.pem;
ssl_certificate_key /etc/nginx/cert/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host ;
proxy_set_header X-Forwarded-Proto https;
}
}
如果你还保留 80 端口,建议直接跳转到 https,别让用户手动猜。
server {
listen 80;
server_name example.com;
return 301 https://;
}
七、静态资源别浪费后端资源
如果你的项目里有图片、JS、CSS、字体这些静态文件,能让 Nginx 直接处理就尽量直接处理。Spring Boot 不是不能干这件事,只是它不该把时间花在这种重复工作上。
静态资源走 Nginx 后,响应更快,后端连接数也更轻松。尤其是首页、管理后台、活动页这种资源比较多的地方,差别很明显。
八、排障时我会先看这四样
遇到问题时,我通常不会马上改配置,而是先看四个点:
- Nginx error.log
- Nginx access.log
- Spring Boot 应用日志
- curl 直接访问后端端口的结果
这个顺序很土,但很管用。因为很多问题不是配置本身错了,而是你压根不知道失败发生在哪一层。curl 一下后端,如果直连没问题,那就回头看 Nginx;如果直连都失败,那就别在代理层上绕太久。
九、给一个可以直接抄的稳妥版本
server {
listen 80;
server_name example.com;
return 301 https://;
}
server {
listen 443 ssl http2;
server_name example.com;
client_max_body_size 50m;
ssl_certificate /etc/nginx/cert/fullchain.pem;
ssl_certificate_key /etc/nginx/cert/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host ;
proxy_set_header X-Real-IP ;
proxy_set_header X-Forwarded-For ;
proxy_set_header X-Forwarded-Proto https;
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
这套配置不花哨,但足够稳。先把访问、转发、证书、上传这几件事跑通,再去细分图片、下载、接口限流、缓存这些更细的模块。
反向代理这件事,真的不是把请求“转过去”那么简单。你越早把边界、超时、头信息、上传限制这些点想清楚,后面越少半夜改配置。系统能稳定跑,通常不是因为某一条配置很神,而是每一个小地方都没偷懒。
评论 (0)