Nginx配置错误导致网络异常故障排查

目录
  1. 1. 一、问题现象
  2. 2. 二、抓包分析
  3. 3. 三、查看 Spring Boot 日志
  4. 4. 四、真正的原因
  5. 5. 五、为什么会提示 CORS?
  6. 6. 六、为什么会出现 worker_connections are not enough?
  7. 7. 七、真正需要排查的不是 Nginx
    1. 7.1. 1、Spring Boot 接口响应过慢
    2. 7.2. 2、数据库慢查询
    3. 7.3. 3、Redis 或第三方接口阻塞
    4. 7.4. 4、WebSocket 或长连接过多
  8. 8. 八、解决方案
    1. 8.1. 方案一:提高 worker_connections
    2. 8.2. 方案二:继续定位真正瓶颈
  9. 9. 九、排查经验总结
  10. 10. 十、总结
    1. 10.1. 排查结论
    2. 10.2. 经验总结

一、问题现象

系统运行过程中,前端偶发出现接口请求失败。

浏览器控制台提示:

1
2
3
4
5
6
Access to XMLHttpRequest at
'https://api.xxx.city/admin-api/hotel/room/getRoomAll?id=10162'
from origin 'https://desk.xxx.city'
has been blocked by CORS policy:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

同时还伴随着:

1
2
GET https://api.xxx.city/admin-api/hotel/room/getRoomAll?id=10162
500 (Internal Server Error)

Axios 最终抛出:

1
2
AxiosError: Network Error
code: ERR_NETWORK

第一眼很容易怀疑:

  • DNS 是否解析异常?
  • CORS 是否配置错误?
  • Spring Boot 是否抛出了异常?

二、抓包分析

查看 Response Header:

1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 500 Internal Server Error
Server: nginx/1.18.0 (Ubuntu)
Date: Wed, 15 Jul 2026 03:38:38 GMT
Content-Type: text/html
Content-Length: 588
Connection: close

Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,Version
Access-Control-Expose-Headers: Content-Length,Content-Range

可以发现:

  • 请求已经到达 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
2
3
4
5
6
2026/07/15 11:38:38 [alert]
worker_connections are not enough
while connecting to upstream

upstream:
http://127.0.0.1:48080/admin-api/hotel/room/getRoomAll?id=10162

终于找到根因。

Nginx 在连接 Spring Boot 时:已经没有可用连接了。因此直接返回:500 Internal Server Error

五、为什么会提示 CORS?

浏览器看到的是:No 'Access-Control-Allow-Origin'

实际上我的 Nginx 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
location /admin-api/ {

add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,Version' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;

if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
...
}

proxy_pass http://pms_backend/admin-api/;
}

可以发现普通请求(GET、POST)并没有返回:Access-Control-Allow-Origin
只有 OPTIONS 请求才设置了。

因此:

  • OPTIONS 请求正常
  • GET 请求返回 500 时没有 Origin Header
  • 浏览器误认为是跨域错误

所以:CORS 只是表现,不是真正原因。

六、为什么会出现 worker_connections are not enough

当前 Nginx 配置:

1
2
3
4
5
worker_processes auto;

events {
worker_connections 768;
}

服务器配置:

1
2
ulimit -n
65535

说明:

  • 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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
浏览器


Nginx


Spring Boot


MySQL 慢查询


30 秒以后才返回


Nginx 连接一直占着


越来越多


worker_connections 耗尽

2、数据库慢查询

如果 MySQL 出现:

  • 慢 SQL
  • 锁等待
  • RDS 性能不足

都会导致接口响应越来越慢。

3、Redis 或第三方接口阻塞

例如:

  • Redis 超时
  • OTA 接口超时
  • HTTP 调用阻塞

都会导致请求堆积。

4、WebSocket 或长连接过多

如果系统存在:

  • WebSocket
  • SSE
  • 长轮询

同样容易耗尽连接。

八、解决方案

方案一:提高 worker_connections

1
2
3
4
5
6
worker_processes auto;

events {
worker_connections 4096;
multi_accept on;
}

修改后执行:

1
2
nginx -t
nginx -s reload

方案二:继续定位真正瓶颈

建议重点排查:

Spring Boot

查看:

  • http-nio-* 请求线程
  • 接口执行耗时
  • Thread Dump(jstack)

MySQL

查看:

  • 慢 SQL
  • 锁等待
  • 活跃连接数

Redis

查看:

  • 是否存在阻塞
  • 是否大量重试

系统连接状态

执行:

1
ss -ant | grep :48080

重点关注:

  • ESTAB
  • CLOSE_WAIT
  • TIME_WAIT

判断连接为什么迟迟不能释放。

九、排查经验总结

很多时候浏览器提示:CORS Error,真正的问题并不是 CORS。

推荐排查顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
浏览器 Console


Network(确认 HTTP Status)


Nginx Error Log


Spring Boot 日志


数据库


Redis / 第三方服务

不要因为浏览器提示:No Access-Control-Allow-Origin就一直修改跨域配置。

真正值得关注的是:HTTP 500,只有找到导致 500 的根因,问题才能彻底解决。

十、总结

本次故障形成了一条完整的故障链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Spring Boot 请求处理变慢(待进一步排查)


Nginx 与 upstream 的连接长期占用


worker_connections(768) 耗尽


Nginx 返回 HTTP 500


500 响应未携带 Access-Control-Allow-Origin


浏览器提示 CORS


Axios 最终抛出 Network Error

排查结论

现象 原因 是否根因
浏览器提示 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 日志 → 应用日志 → 数据库 的顺序进行定位,而不是一开始就怀疑跨域配置。