一、问题现象
系统运行过程中,前端偶发出现接口请求失败。
浏览器控制台提示:
1 | Access to XMLHttpRequest at |
同时还伴随着:
1 | GET https://api.xxx.city/admin-api/hotel/room/getRoomAll?id=10162 |
Axios 最终抛出:
1 | AxiosError: Network Error |
第一眼很容易怀疑:
- DNS 是否解析异常?
- CORS 是否配置错误?
- Spring Boot 是否抛出了异常?
二、抓包分析
查看 Response Header:
1 | 500 Internal Server Error |
可以发现:
- 请求已经到达 Nginx
- 返回的是 HTTP 500
- 并没有
Access-Control-Allow-Origin(因为一个响应头中不能出现两次Access-Control-Allow-Origin,因为已经在后端添加了,因此在nginx中重复配置,所以这个不是问题)
因此:
浏览器提示 CORS,只是因为 500 响应没有携带
Access-Control-Allow-Origin,真正的问题还是 HTTP 500。
而且Content-Type: text/html,而非:Content-Type: application/json,说明500是nginx返回的,不是后端程序返回的。
此时可以排除:
- DNS 解析失败
- SSL 握手失败
- 网络不通
三、查看 Spring Boot 日志
Spring Boot 日志中发现了一些异常,例如:java.lang.NullPointerException,以及:ServiceException: 产品查询为空
但是这些异常全部发生在:queue-2线程中,例如:MeituanAriConsumer,属于 Redis MQ 消费线程。
浏览器访问的是:GET /admin-api/hotel/room/getRoomAll
对应的 Spring MVC 请求线程应该是:http-nio-48080-exec-*
因此这些 Redis 消费异常虽然需要处理,但并不是导致 HTTP 500 的直接原因。
四、真正的原因
查看 Nginx Error Log:
1 | 2026/07/15 11:38:38 [alert] |
终于找到根因。
Nginx 在连接 Spring Boot 时:已经没有可用连接了。因此直接返回:500 Internal Server Error。
五、为什么会提示 CORS?
浏览器看到的是:No 'Access-Control-Allow-Origin'
实际上我的 Nginx 配置如下:
1 | location /admin-api/ { |
可以发现普通请求(GET、POST)并没有返回:Access-Control-Allow-Origin
只有 OPTIONS 请求才设置了。
因此:
- OPTIONS 请求正常
- GET 请求返回 500 时没有 Origin Header
- 浏览器误认为是跨域错误
所以:CORS 只是表现,不是真正原因。
六、为什么会出现 worker_connections are not enough?
当前 Nginx 配置:
1 | worker_processes auto; |
服务器配置:
1 | ulimit -n |
说明:
- Linux 文件描述符充足
worker_processes auto也没有问题
真正限制的是:
1 | worker_connections 768 |
它表示: 每个 Worker 最多只能维护 768 个连接。
连接不仅包括客户端请求,还包括:
- 浏览器连接
- KeepAlive 连接
- Upstream 连接
- HTTP/2
- WebSocket
- SSE
一旦连接长期不能释放,就容易耗尽。
七、真正需要排查的不是 Nginx
把:
1 | worker_connections 768; |
改成:
1 | worker_connections 4096; |
确实可以缓解问题。
但是: 这通常只是缓解,而不是根治。
真正需要继续排查的是:为什么连接一直没有释放?
常见原因包括:
1、Spring Boot 接口响应过慢
例如:
1 | 浏览器 |
2、数据库慢查询
如果 MySQL 出现:
- 慢 SQL
- 锁等待
- RDS 性能不足
都会导致接口响应越来越慢。
3、Redis 或第三方接口阻塞
例如:
- Redis 超时
- OTA 接口超时
- HTTP 调用阻塞
都会导致请求堆积。
4、WebSocket 或长连接过多
如果系统存在:
- WebSocket
- SSE
- 长轮询
同样容易耗尽连接。
八、解决方案
方案一:提高 worker_connections
1 | worker_processes auto; |
修改后执行:
1 | nginx -t |
方案二:继续定位真正瓶颈
建议重点排查:
Spring Boot
查看:
http-nio-*请求线程- 接口执行耗时
- Thread Dump(jstack)
MySQL
查看:
- 慢 SQL
- 锁等待
- 活跃连接数
Redis
查看:
- 是否存在阻塞
- 是否大量重试
系统连接状态
执行:
1 | ss -ant | grep :48080 |
重点关注:
- ESTAB
- CLOSE_WAIT
- TIME_WAIT
判断连接为什么迟迟不能释放。
九、排查经验总结
很多时候浏览器提示:CORS Error,真正的问题并不是 CORS。
推荐排查顺序:
1 | 浏览器 Console |
不要因为浏览器提示:No Access-Control-Allow-Origin就一直修改跨域配置。
真正值得关注的是:HTTP 500,只有找到导致 500 的根因,问题才能彻底解决。
十、总结
本次故障形成了一条完整的故障链:
1 | Spring Boot 请求处理变慢(待进一步排查) |
排查结论
| 现象 | 原因 | 是否根因 |
|---|---|---|
| 浏览器提示 CORS | 500 响应未返回 Access-Control-Allow-Origin |
❌ |
Axios Network Error |
浏览器因跨域策略屏蔽了 500 响应 | ❌ |
| HTTP 500 | Nginx 无法建立新的 upstream 连接 | ⚠️ |
worker_connections are not enough |
Nginx Worker 连接耗尽 | ⚠️ |
| Spring Boot 请求耗时过长 / 后端连接长期占用 | 导致 Nginx 连接无法及时释放 | ✅(最终需要继续排查) |
经验总结
浏览器提示的错误往往只是表象。
本次故障中:
- CORS 不是根因;
- DNS 也没有任何问题;
worker_connections不足只是触发了 500;- 真正值得继续排查的是 为什么 Spring Boot 与数据库、Redis 等后端资源响应变慢,导致 Nginx 连接长期占用。
对于这类问题,建议优先从 HTTP 状态码 → Nginx 日志 → 应用日志 → 数据库 的顺序进行定位,而不是一开始就怀疑跨域配置。