PHP 项目架构性能瓶颈问题请教

2020-12-30 15:40:23 +08:00
 yuandj

环境:

服务器

问题描述

  1. 目前项目在 qps 较高时遇到了响应时间延长的问题,新增了一台 api 服务器,并没有多大改善(原本是 3 台)
  2. 大概看了一下高并发时服务器的负载,并没有达到上限
  3. 平时 qps 可以支撑 1000 左右(3 台服务器),响应延迟保持在 450ms 左右。这两天请求增多 qps 达到 1300 左右,每个小时有十几分钟响应延迟会增加(多的时候响应会达到 3 、4 秒)(下面会附图),前 2 条大概排除了服务器的问题,现在考虑代码问题。下面附图把代码流程加了 time debug,并附带上比较耗时的代码段,麻烦各位大佬帮忙看看代码有没有性能瓶颈问题。

ps: 之前有段时间也遇到响应延迟问题,当时 time debug 定位到 redis get 操作耗时比较多(当时是 2 秒左右),但并没有在这方面做修复,后面通过减少了 swoole 的进程数解决了。

请求延迟监控图

每个小时的开始,请求会比较集中

请求流程时间拆分图

发现 qps 相关的代码段执行时间比较长,下面附上相关代码段

QPS 相关代码段

5622 次点击
所在节点    PHP
40 条回复
ebingtel
2020-12-30 17:59:18 +08:00
redis 用池化连接了么?
liuhan907
2020-12-30 19:52:08 +08:00
我建议你可以考虑接入 prometheus,细致的分析每个操作的耗时。能更加精确的定位瓶颈。
zhuzhibin
2020-12-30 20:19:08 +08:00
我就想问协程框架好不好用 上手如何?
AlanLeung2018
2020-12-30 20:21:46 +08:00
先排查是不是 mysql 慢查询造成的慢请求,然后再检查一下是不是某个时间段 fpm 进程数太多了
iConnect
2020-12-30 20:28:55 +08:00
这个情况大概率是 redis 的故障,先把 redis 服务器扩容或提高配置,或者干脆切到云服务商的专业 redis 云跑一段时间,对比一下,基本上就能诊断出来了。
honkki
2020-12-30 23:16:30 +08:00
redis 的配置是否有问题
sagaxu
2020-12-31 00:25:33 +08:00
1. 先确认 php 的 redis 用了连接池,池的大小,空闲多少
2. for 循环里每次两个 incr,10 个 config 的时候就是 20 个 incr,考虑做成批量更新
dusu
2020-12-31 02:31:09 +08:00
显然是 redis pool 到了最高并发量 导致 hyperf worker 协程都卡在了 redis 这头 而 redis 又查不出慢查询的原因

建议把 qps 部分或者高频又低重要性的 redis 操作都换成 asyncQueue 或者其他异步单线程任务试试看看协程能不能缓解。
chenqh
2020-12-31 03:20:29 +08:00
感觉是不是 redis get 的一些值字节太大?
sadfQED2
2020-12-31 08:29:13 +08:00
先确认一下硬件资源占用,每台机器的硬盘 io,网络 io,cpu,内存

先确定不是内存以后再定位是哪台机器。

另外,项目里面建议引入 opentarcing
sadfQED2
2020-12-31 08:30:08 +08:00
@sadfQED2 不是内存等硬件
少打几个字了
surfire91
2020-12-31 08:31:01 +08:00
@yuandj
"确实有一些 incr set get 时间比较长,超过了 10000 微秒,但是图中 qps_incr_time 代码段执行时间是 170 毫秒,那么这么大的差距是哪里来的呢?"

qps_incr_time 代码段 里遍历了一个数组 configs,每个元素要执行两次 redis incr, 如果 configs 元素的数量多几个,执行 170ms 也正常。

另外 redis incr 需要 10ms 的话,肯定是不正常的。
dedemao
2020-12-31 08:57:56 +08:00
请教下“请求延迟监控图”和“请求流程时间拆分图”是如何获取的呢
fuxkcsdn
2020-12-31 09:13:17 +08:00
skipConfig 里的 $cUsedQps, $pUsedQps 这 2 个可以用 mget 来获取

incrQps 方法
可以通过 pipe 或者事务来执行,速度会提高很多
如果 incrQps 里那个循环量很大的话,那直接改这里性能就能有很大提升了
jeristiano
2020-12-31 10:42:43 +08:00
建议你去 hyperf 官方群去问问,他们经常为用户提供建议和反馈
qq 862099724
yuandj
2020-12-31 10:44:57 +08:00
@dedemao 监控是用的 hyperf 手册里推荐的,你可以在手册里搜索关键字“ Grafana”;请求流程拆分图,是自己打的日志
mpanda
2020-12-31 12:00:18 +08:00
第一直觉,反正不是 php 的锅
sagaxu
2020-12-31 12:23:22 +08:00
咱们好像是同行,这个行业 qps 做到单机 1 万才算及格,rtb 响应时间(含网络)一般不宜超过 200ms 。不含 dmp 的纯 dsp,单机普遍能做到 10 万 qps 。
yuandj
2020-12-31 15:51:49 +08:00
@fuxkcsdn incr 用 pipe 来操作,执行时间有所改善;但是 skipConfig 用 mget(),却比之前消耗了更多时间,请问是什么原因呢?
fuxkcsdn
2021-01-02 01:34:41 +08:00
@yuandj mget 消耗更多时间,是多次对比结果吗?
从源码上看 mget 只是 get 的循环并组装 reply,理论上能抵消网络消耗才对
一种可能就是当前 redis 服务器已经超过负荷,组装 reply 的损耗超过 1 次网络请求的损耗了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/740346

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX