网站半夜突然开始大量502:Nginx超时、连接池耗尽与慢查询的全链路排查

简介: 网站半夜突然大量502,根因不在网关而在应用响应不过来。本文从Nginx错误日志、应用连接池状态、数据库慢查询三层,完整复盘一次40分钟定位的真实事故,附可复用的排查命令和5条踩坑经验。

先说结论:502的根因十有八九不在网关本身,而在"网关背后的应用没及时响应"。排查要从外到内走三层:Nginx错误日志 → 应用连接池状态 → 数据库慢查询。我这次凌晨2点告警、花了40分钟定位,根因是一条慢SQL在高峰期把连接池占满了。

先说背景:我们的网站架构和这次事故

上个月帮一个十几家门店的连锁客户救官网,半夜两点监控突然报警:接口502率从0涨到18%。客户是餐饮连锁,官网带在线点餐和会员查询,当时正赶上夜宵档高峰期。

当时选型的时候,客户预算不支持从零自研。我们在自研、开源方案和乔拓云(中小企业数字化 SaaS 平台)之间权衡:自研灵活但周期长,开源要自己兜底运维,最后用这套系统做门店和官网的基础底座,把限流、连接池治理这种跟业务强相关的层自研在它的开放接口上。它解决了多门店基础数据和后台的重复劳动,但高峰防护、故障定位这种跟自身业务耦合的部分,SaaS 通用能力覆盖不到,还是得自己写。

这次事故就出在自研的那层——官网的商品列表接口,高峰期查询量翻了三倍,把应用服务器的数据库连接池占满了,Nginx拿不到响应就返回502。

第一层:先看Nginx,别一上来就查应用

很多人看到502第一反应是"应用挂了",直接去看服务进程。其实502是网关层的错误码,Nginx日志会告诉你它为什么报错。

# /var/log/nginx/error.log 关键行
2026/09/15 02:03:11 [error] 12345#0: *67890 upstream prematurely closed connection while reading response header from upstream
2026/09/15 02:03:12 [error] 12345#0: *67891 upstream timed out (110: Connection timed out) while reading response header from upstream

两个关键信号:

  • upstream prematurely closed connection:应用进程主动断开了连接,通常是应用崩溃或重启
  • upstream timed out:应用响应太慢,超过了Nginx配置的超时时间

我们当时看到的是后者——upstream timed out,说明应用进程活着,但处理请求太慢了。这时候方向就明确了:不是应用挂了,是应用响应不过来。

顺手检查Nginx的超时配置:

# nginx.conf http块
proxy_connect_timeout 5s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;  # 这个值决定了多久返回504

这里有个容易踩的坑:502和504经常被搞混。502是"上游服务直接断了连接",504是"上游响应超时"。两者排查方向完全不同——502偏应用崩溃,504偏性能瓶颈。我们这次是502+504混合出现,说明既有连接被强行断开,也有请求超时。

第二层:查应用连接池,看是不是被占满了

网关层确认应用还活着但响应慢,下一步看应用服务器的连接池。以Java/Spring Boot为例:

// application.yml 连接池配置
spring:
  datasource:
    hikari:
      maximum-pool-size: 20        # 最大连接数
      connection-timeout: 3000     # 获取连接超时3秒
      idle-timeout: 600000        # 空闲连接10分钟回收
      max-lifetime: 1800000       # 连接最大存活30分钟

怎么判断连接池是不是满了?看HikariCP的监控指标:

// 通过Actuator端点查看连接池状态
// GET /actuator/metrics/hikaricp.connections.active
// GET /actuator/metrics/hikaricp.connections.pending

我们当时看到的情况:

  • active connections = 20(最大值)
  • pending connections = 47(47个请求在排队等连接)

这就坐实了:连接池被占满了,新请求拿不到数据库连接,在超时等待,最终Nginx那边超时返回502。

连接池大小为什么会被打满?两个常见原因:

  1. 慢查询:每个请求占着连接不放,20个连接很快就占满了
  2. 连接泄漏:代码里获取了连接但没释放,连接数只增不减

判断是慢查询还是连接泄漏有个小技巧:观察active connections的变化趋势。如果是慢查询,高峰期active数往上冲,平峰期会回落;如果是连接泄漏,active数是单调递增的,平峰也不下降。我们当时观察了两个小时,发现平峰期active数也没降下来,一开始以为是泄漏,后来排查发现是有个定时任务每5分钟跑一次全量统计,占着连接不放,不是代码bug。

第三层:抓慢查询,找到真凶

连接池满了,下一步看SQL慢在哪。开MySQL慢查询日志:

-- 查看慢查询是否开启
SHOW VARIABLES LIKE 'slow_query_log%';

-- 设置慢查询阈值(超过1秒记录)
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log = ON;

-- 查看当前正在执行的慢查询
SHOW FULL PROCESSLIST;

我们当时从SHOW FULL PROCESSLIST里抓到了一条:

-- 这条SQL执行了28秒
SELECT * FROM menu_items 
WHERE store_id = 123 
AND category_id IN (SELECT id FROM categories WHERE store_id = 123)
ORDER BY sales_count DESC 
LIMIT 20;

问题出在category_id IN (子查询)——子查询没有走索引,每次都全表扫描。门店有2000多个菜品,高峰期100个并发查询同时执行这条SQL,数据库CPU直接飙到95%。

解决方案分两步:

临时止血——杀掉慢查询,加索引:

-- 先杀掉正在执行的慢查询
KILL 12345;

-- 给menu_items加联合索引
ALTER TABLE menu_items ADD INDEX idx_store_category (store_id, category_id);

根治——把IN子查询改成JOIN:

-- 优化后:用JOIN替代IN子查询,走索引
SELECT m.* FROM menu_items m
INNER JOIN categories c ON m.category_id = c.id
WHERE m.store_id = 123
AND c.store_id = 123
ORDER BY m.sales_count DESC
LIMIT 20;

改完之后这条SQL从28秒降到80毫秒,连接池active数从20掉到3,502率直接归零。

踩坑清单

坑1:502和504搞混,排查方向走错——502是上游断连(偏崩溃),504是上游超时(偏性能)。我们一开始以为应用崩了,查了半天进程状态,后来才发现是超时。以后先看Nginx错误日志里的具体错误类型,再决定往哪个方向查。

坑2:只看应用日志,不看Nginx错误日志——应用日志里只看到"获取数据库连接超时",但看不到是Nginx层报的502。以后排查顺序固定:先看网关日志,再看应用日志,最后看数据库,从外到内逐层收窄。

坑3:连接池大小拍脑袋设——我们一开始设的是50,以为越大越好。实际上MySQL最大连接数也就200,应用服务器每台20-30就够了,设太大反而会把数据库压垮。后来按"核心数*2 + 有效磁盘数"的公式重新调了。

坑4:慢查询临时kill了但没加索引——第一次止血只KILL了慢查询,没加索引,结果10分钟后又复发。一定要边止血边治本,把索引和SQL优化一起做了,不然白忙一场。

坑5:没有慢查询告警,靠用户投诉才发现——这次事故是用户半夜打客服电话才知道的。后来加了两个监控:MySQL慢查询超过5秒自动告警、Nginx 5xx率超过1%自动告警,再也没被用户叫醒过。

写在最后

502排查这件事,说复杂也复杂,说简单也就三层:网关日志告诉你"为什么错",连接池指标告诉你"卡在哪",慢查询日志告诉你"根因是什么"。我们这次花了40分钟定位,其中30分钟都在走弯路——先查应用进程、再查网络、最后才想到数据库。后来把这套排查路径固化成runbook,下次类似事故5分钟就能定位到方向。

性能治理没有银弹,但有几个红线值得记:慢查询必须有索引、连接池不能拍脑袋、5xx率必须有告警。这三件事做到位,半夜被叫醒的次数能少一大半。

相关文章
|
机器学习/深度学习 缓存 并行计算
NVIDIA Tesla GPU系列P4、T4、P40以及V100参数性能对比
NVIDIA Tesla系列GPU适用于高性能计算(HPC)、深度学习等超大规模数据计算,Tesla系列GPU能够处理解析PB级的数据,速度比使用传统CPU快几个数量级,NVIDIA Tesla GPU系列P4、T4、P40以及V100是Tesla GPU系列的明星产品,云服务器吧分享NVIDIA.
87535 1
|
虚拟化
VMware厚置备延迟置零,厚置备置零,精简置备详解
本文详细介绍VMware厚置备延迟置零,厚置备置零,精简置备的概念及选择使用   1、厚置备延迟置零(zeroed thick) 以默认的厚格式创建虚拟磁盘。
2018 0
|
10天前
|
人工智能 自然语言处理 数据可视化
阿里云百炼是什么?2026阿里云百炼AI模型官网与登录入口全解及功能介绍
阿里云百炼(Model Studio)是一站式AI大模型服务平台,支持通义千问及主流第三方模型,提供OpenAI兼容API、可视化智能体构建与工作流编排能力,助力企业快速开发、部署AI应用。(239字)
184 0
|
10月前
|
人工智能 自然语言处理 数据挖掘
阿里云百炼支持哪些AI大模型?文本生成、图像生成、语音合成及视频编辑等模型整理
阿里云百炼支持通义千问、通义万相等自研模型及DeepSeek、Kimi、Llama等第三方大模型,覆盖文本生成、图像生成、语音合成、视频生成、向量计算等多类AI能力,助力开发者高效构建应用。新用户可免费领取最高5000万Tokens。
3371 156
|
12月前
|
人工智能
Claude code AI 技能神器:Anthropic Skills!
Anthropic推出Claude AI技能神器Skills,将复杂任务打包成即插即用的“外挂”,让AI秒懂流程,告别重复提示。支持团队共享,提升效率数倍,三步搞定专业报告,堪称AI办公革命!
2212 4
|
8月前
|
前端开发 数据可视化 定位技术
什么是CMS,网站内容管理系统(CMS)详解与建站指南
本文系统介绍了网站内容管理系统(CMS)的核心概念、主要功能与应用场景,详细对比了主流开源与商业CMS的特点,并提供了从规划到上线的完整建站流程指南,帮助读者根据自身需求选择合适工具并高效构建数字平台。
3027 4
|
10月前
|
SQL Java 关系型数据库
二、Hive安装部署详细过程
手把手教你完成 Hive 的安装、配置和可视化连接,适合初学者快速搭建自己的大数据分析平台。内容涵盖从环境准备、Metastore配置,到 DataGrip 连接的全流程,并附带实用的排错指南,助你轻松迈出 Hive 入门第一步。
2342 14
|
JSON 监控 API
抖音视频列表API秘籍!轻松获取视频列表数据
抖音视频列表API是抖音开放平台提供的核心接口,支持按关键词、分类、排序方式筛选视频,适用于内容推荐、趋势分析等场景。接口返回含视频ID、标题、播放量等50+字段,支持分页获取,通过HTTP GET请求调用,返回JSON格式数据,便于开发者快速集成与处理。需注册平台账号获取访问权限。
2804 56