免费监控
logo prod

资讯与帮助

实战排查:一次由HTTP监控告警引发的504 Gateway Timeout问题定位记

时间:2025-04-24
编辑:tance.cc

HTTP监控驱动504.png

对于负责网站稳定性的我们来说,深夜的告警声往往是肾上腺素飙升的开始。就在上周二凌晨3点,寂静被观图数据(GuanTu Data)平台急促的告警通知打破:我们核心业务API的一个关键接口 /api/v1/processOrder 的HTTP监控任务,开始连续报告 “504 Gateway Timeout” 错误

504错误!这意味着用户发起的请求,在经过我们的Nginx网关时,等待后端应用服务器(PHP-FPM)的响应时间过长,最终被网关无情地“挂断”了。这通常指向后端服务的严重问题,直接影响核心业务流程,必须立即处理!

第一步:告警信息分析(监控数据的价值)

我们首先冲到观图数据的监控面板,查看告警详情和相关数据:

  • 确认错误: 确实是 504 Gateway Timeout,不是网络波动导致的瞬时错误。

  • 影响范围: 告警来自我们部署的多个地理位置的监控节点(北京、上海、硅谷),说明这不是区域性的网络问题,而是源头服务的问题。

  • 发生时间: 错误从凌晨 3:00 左右开始集中出现,并且持续不断。

  • 关联指标: 查看该接口HTTP监控的响应时间(Response Time)和TTFB(首字节时间)图表,发现在3:00之前,TTFB 就有逐步升高的趋势,并在错误爆发点急剧恶化或直接超时。这进一步印证了问题出在后端处理环节

第二步:基于504的特性,建立排查假设

504的核心是“后端未及时响应”。基于此,我们列出了几个最可能的“嫌疑人”:

  1. 后端 PHP-FPM 服务挂了或僵死了?

  2. /api/v1/processOrder 接口的处理逻辑耗时过长,超过了 Nginx 设置的超时时间?

  3. 后端服务器资源(CPU、内存、磁盘I/O)耗尽,无法处理新请求?

  4. Nginx 与 PHP-FPM 之间的网络通信有问题?

  5. 接口依赖的数据库服务响应缓慢或锁死?

第三步:逐一验证假设(定位过程)

我们登录到后端应用服务器,开始了紧张的排查:

  1. 检查PHP-FPM服务状态:

    Bash

    systemctl status php-fpm

    输出显示 active (running)。看来服务本身没宕机,初步排除假设1。

  2. 检查服务器资源:使用 topfree -m 命令观察。CPU使用率尚可,但 free -m 显示:

              total        used        free      shared  buff/cache   available
    Mem:         15885        14100         785          12        1000        1100
    Swap:         4095         3100         995

    物理内存剩余不多(free只有785M),并且Swap被大量使用(used 3100M)。内存压力大,这是一个重要的疑点! 高Swap使用通常意味着系统性能会急剧下降。

  3. 检查Nginx错误日志:在Nginx网关服务器上查看 error.log

    2025/04/24 03:05:10 [error] 12345#12345: *67890 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 1.2.3.4, server: api.yourdomain.com, request: "POST /api/v1/processOrder HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm/php-fpm.sock", host: "api.yourdomain.com"

    日志明确记录了 upstream timed out,确认是 Nginx 等待 FastCGI (PHP-FPM) 响应超时。这与监控结果一致,但还没找到PHP-FPM超时的原因。

  4. 检查PHP-FPM慢日志:我们配置了PHP-FPM慢日志来记录执行时间过长的脚本。查看慢日志文件 (www-slow.log):

    [24-Apr-2025 03:06:15] WARNING: [pool www] child 12345 script '/var/www/html/api/v1/processOrder.php' (request: "POST /api/v1/processOrder") execution timed out (65.123456 sec), terminating
    script_filename = /var/www/html/api/v1/processOrder.php
    [0x00007fabcdef1234] processOrder() /var/www/html/api/v1/processOrder.php:15
    [0x00007fabcdef5678] handleRequest() /var/www/html/index.php:10

    大量的 /api/v1/processOrder 请求执行时间超过了我们 Nginx 配置的 fastcgi_read_timeout(假设是60秒),直接被 PHP-FPM 自身或 Nginx 超时终止了。问题核心锁定在 /api/v1/processOrder 这个脚本执行过慢!

  5. 分析慢请求与数据库:结合慢日志中的堆栈信息,我们定位到 processOrder() 函数中一个用于更新订单状态并记录日志的复杂SQL查询。通过 EXPLAIN 分析该SQL,发现它涉及多表JOIN,并且其中一个关键的关联字段缺少索引。同时,我们回想起凌晨3点系统会启动一个订单归档的定时任务,这个任务会对相关表产生大量读写,进一步加剧了数据库负载,使得那个本就效率不高的查询变得雪上加霜,最终导致大面积超时。内存压力大也可能是由于PHP处理这些慢查询时消耗了过多内存所致。

第四步:制定并实施解决方案

原因找到,解决方案就清晰了:

  1. SQL优化: 为涉及的数据库表添加合适的索引,优化那个复杂的JOIN查询。

  2. 定时任务调整: 评估是否可以将订单归档任务的时间错开,避开API调用相对还活跃的时段,或者优化归档任务本身的效率,减少其对数据库的冲击。

  3. 资源监控与评估: 虽然暂时通过SQL优化解决了问题,但内存压力大的问题仍需关注。后续需要结合更长时间的资源监控数据,评估是否需要增加服务器内存。

  4. (可选) 超时调整: 在确认SQL和任务优化到位后,可以根据实际情况微调 Nginx 的 fastcgi_read_timeout 和 PHP 的 max_execution_time,使其既能覆盖正常处理时间,又不会设置过长导致资源被无效占用。

第五步:验证修复效果

在实施了SQL优化和调整定时任务后,我们密切关注观图数据的HTTP监控:

  • 504错误迅速消失,接口恢复了200 OK状态。

  • TTFB和整体响应时间也显著下降,回到了正常水平。

  • 持续观察了几个小时,未再出现超时告警。问题确认解决!

复盘与启示

这次深夜的“救火行动”再次印证了:

  1. HTTP监控是生命线: 没有监控告警,我们可能要等到早上用户反馈甚至业务受损时才发现问题。监控为我们赢得了宝贵的响应时间。

  2. 错误代码指导方向: 504错误直接将我们的注意力引向了后端响应能力和超时问题,避免了在网络层或Nginx配置上浪费过多时间。

  3. 日志是关键证据: Nginx错误日志和PHP慢日志是定位具体超时的核心依据。确保日志记录开启且配置合理非常重要。

  4. 性能问题往往是复合因素: 单一的慢查询可能平时只是“有点慢”,但在特定条件下(如高并发、定时任务、资源紧张)就会被放大,成为压垮骆驼的最后一根稻草。

  5. 监控驱动优化: 通过监控发现问题,解决问题,再通过监控验证效果,形成一个闭环,持续提升系统稳定性。

这次经历也提醒我们,对于核心业务接口,不仅要监控其可用性(状态码),更要关注其性能(响应时间、TTFB)并设置合理的阈值告警,这样才能更早地发现潜在的性能退化问题,防患于未然。


客服
意见反馈