CPU密集型PHP API高并发返回503 Bad Gateway的优化咨询
你遇到的503错误确实是并发请求上升后,每次请求都重复执行全量查询、多轮循环计算逻辑,CPU和数据库连接资源耗尽导致的。你提到的定时脚本预生成数据的方案是可行的,还有更多改造成本更低、效果更好的优化方案,按优先级排序如下:
1. 优先加缓存,最快降低负载
- 用内存缓存(如Redis)存储预计算好的接口返回JSON数据,缓存有效期和你的K线周期对齐即可。所有请求先读缓存,命中直接返回,仅当缓存过期时才执行一次查询和计算逻辑,99%以上的请求都不用跑计算逻辑,CPU占用会直接降到个位数。
- 如果不想额外部署缓存服务,你提到的定时预生成方案也可以落地:按你的K线最小更新周期跑定时任务,后台预计算结果后写入静态JSON文件,前端服务器直接返回静态文件,连PHP解析都不需要,性能更高。注意写入时先写临时文件再执行rename操作,避免请求读到不完整的文件报错。
2. 优化现有查询和代码,降低单请求耗时
就算没有缓存,优化后单请求CPU耗时可以降低80%以上,能承载更多并发:
SQL优化
你现有SQL有大量冗余:SELECT *实际只用到3个字段,LIKE 'name'属于等值匹配可以换成=,还能走索引。修改后SQL如下:
SELECT 日期字段名,价格字段名,datetime FROM `table` WHERE name = 'name' ORDER BY datetime ASC
给name和datetime加联合索引,避免全表扫描,查询速度可以提升数倍。
更极致的优化是直接用SQL完成OHLC计算,不需要PHP循环处理:
SELECT UNIX_TIMESTAMP(datetime) DIV :timer * :timer as time, FIRST_VALUE(price) OVER (PARTITION BY UNIX_TIMESTAMP(datetime) DIV :timer * :timer ORDER BY datetime ASC) as open, MAX(price) as high, MIN(price) as low, LAST_VALUE(price) OVER (PARTITION BY UNIX_TIMESTAMP(datetime) DIV :timer * :timer ORDER BY datetime ASC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as close FROM `table` WHERE name = 'name' ORDER BY time ASC
数据库直接返回你需要的K线结构,PHP仅需转JSON返回即可,完全省去循环计算的CPU开销。
代码冗余优化
你现有代码中先拼接逗号分隔字符串再explode拆分的逻辑完全没必要,纯浪费CPU,直接在查询时写入数组即可:
$response = []; while ($row = mysqli_fetch_row($result)) { $response[] = [strtotime($row[2]), $row[0], $row[1]]; }
这一步可以省去三次大字符串拼接和三次数组拆分的开销,数据量大的时候CPU占用降低非常明显。
3. 高并发场景架构优化
如果后续请求量继续上涨,可以做以下优化:
- 数据库加读写分离,所有查询请求走从库,避免影响主库业务
- 静态化的JSON结果前面加CDN缓存,边缘节点直接返回请求,不需要打到源站
内容的提问来源于stack exchange,提问作者tonni89 marsent
相关产品推荐
相关产品推荐

