关于 PHP 高并发,请教各位

2022-05-26 09:53:36 +08:00
 minuo0day

H5 页面的核酸系统,前后端分离,前端 VUE ,后端 PHP 自己搭的 larave 框架,数据库 mysql,Nginx , 三台负载均衡的天翼云应用服务器,都是 32 核 64G ,一台数据库服务器 16 核 32G ; 基本业务逻辑: 用户端,进入页面绑定自己身份证号手机号乡镇信息等个人信息,前端凭借身份证号直接生成个人二维码,向医护人员出示二维码,1 个小时需要做 40 万人口的核酸; 医护端,手机号身份证号登录或者申请,登入先选采集点,扫开箱码,再扫试管码选择十合一或二十合一,再点击添加人员打开扫一扫扫居民个人码添加;

24 日早上 4 点 30 ,医护人员开始大量的开始进入程序扫箱码开箱,并在后台开始大量的添加临时采集点,于 4 点 58 分,CPU 使用率 100%,系统崩溃,日志显示,瞬间请求数 1 万 4 ,重启在进入还是崩;

24 日下午系统整体挪到阿里云服务器,也是三台负载均衡的服务器,三台 32 核 64G ,加了 OSS ,用了阿里云的云数据库 RDS 版,主实例 8 核 16G ,只读数据库服务器 8 核,压测 10 分钟 15 万人,和 4000 医护人员同时在线也崩了,数据库和应用服务器的 CPU 利用率都打到了 100%,为了保障第二天不出问题,临时调大了一台应用服务器调到了 52 核,并同时把读写的两台数据库服务器都调到了最大 104 核,第二天检测才扛过去。

问:我们虽然调大了服务器的配置,但调大以后压测 10 分钟 20 万人和 4000 医护在线,服务器承载 20%都上不去,但前端页面会变得非常慢,基本上 10 几秒才能打开,这种情况请大神指点

18669 次点击
所在节点    PHP
220 条回复
awanganddong
2022-05-26 11:16:56 +08:00
用户端用户注册 //这个没啥好办法,直接数据库硬抗。
进入页面绑定自己身份证号手机号乡镇信息等个人信息 //这个环节加个 redis 队列,异步写入库操作。laravel 还是非常快速支持的。用户同步信息之后,把核心信息写入 redis hash 或者 string 都可以
前端凭借身份证号直接生成个人二维码, //这个环节对后端直接走缓存
向医护人员出示二维码,1 个小时需要做 40 万人口的核酸;//这个地方就完全走 cdn


像这种业务是非常适合引入 redis 这种缓存的。
minuo0day
2022-05-26 11:20:28 +08:00
@awanganddong 忘记说了,我们是做了 redis 的
telun
2022-05-26 11:20:30 +08:00
数据库都 100%的话肯定不光是 php 这头的问题,查问题先把死锁什么的问题排除吧。
web 端的问题直接 k8s ,硬抗就是了,之后再去慢慢调优,对于高计算量的功能点迁移到函数计算 fc 上去。
weiwenhao
2022-05-26 11:25:26 +08:00
检查服务器日志和数据库日志(云服务和 rds 都有监控的)确定一下问题瓶颈是什么
如果是 php 这边的瓶颈: https://learnku.com/laravel/t/24559 (另外最重要的是 opcache ,如果兼容的话最好把 php 版本和 laravel 版本都提升上去)
如果是数据库的瓶颈: 先看慢查询日志,并发查询的语句,检查索引有没有。并发特别高的语句,临时加一个缓存应该也是很快实现的。

话说前端很慢,直接 f12 看看是请求静态资源慢还是请求接口慢呀
darkengine
2022-05-26 11:27:58 +08:00
我也觉得瓶颈在数据库,按照你描述的业务,应该会经常访问到重复的数据,加层 redis 吧。
codespots
2022-05-26 11:29:23 +08:00
PHP 性能不至于这么拉胯,看看数据库问题,还有前端尽量和服务分开部署在不同服务器上,CDN 赶紧用上,Redis 也加上
awanganddong
2022-05-26 11:29:55 +08:00
一般我排查思路是这样的,
首先配置 nginx 日志,
接着就是 shell 脚本对 nginx 超时时间进行排序
查找超时且请求时间比较长的接口,
这时候你就要分析造成这种情况的原因了,
如果可以加缓存的话,就引入缓存,
其实就是查看数据库的查询情况,explain 一波。


一般情况下都是数据库使用不当引起的。
如果没法优化的话,那就稍微花点钱整个数据库主从分离。
服务器也是可以用平台的弹性伸缩。

基本上以上方法用了还不管用,
那就要考虑你们设计有问题了。


像这种业务应该不太会牵扯到多表联查这种情况
xiaomada
2022-05-26 11:31:44 +08:00
phper 的话高并发场景可以考虑 webman ,workerman 官方出品 数据库组件直接用的 laravel 的,无缝迁移。
janda
2022-05-26 11:33:11 +08:00
框架是没法变的了、只能看看其他方面有没有优化的可能,我们最近也在高并发有些解决方案供参考

- 降低高并发接口与数据库连接
- 添加对应的数据库索引
- nginx 压缩静态资源缓存
- 高并发查询接口使用 redis 等缓存
- 不及时响应数据丢 MQ 慢慢消费
- 前端 cdn
- 集群负载均衡等

例如我们注册的时候是个高并发、但是每次注册前会查询(select)下当前用户是否已注册过!然后在添加(insert)、后来我们就添加唯一索引、不查询,直接添加根据唯一索引的特性来判断最终处理结果、程序捕获异常!

还有一个高并发查询接口也是、因为数据并发没分每秒变动所以、我们用的 redis 缓存设置随机短期时间,但是高并发下会有雪崩穿透击穿的问题
kakaryan
2022-05-26 11:36:22 +08:00
你现在做的是对的,先做升级配置的 scale up ,撑着。
为什么卡住原因没有找到,感觉你的压测没有完全实现测试的目标,压测的目标是找到瓶颈点,不是证明你的并发能力。
你在 24 日下午压测,数据库和业务服务器都崩了,那么说明数据库扛不住,因为数据库崩了业务服务器肯定工作不了的。
从你最后压测服务器负载上不去的情况来看,目前瓶颈在数据库上。
是什么业务造成了数据库的压力?是写数据的压力还是读数据的压力?到底是什么动作带来数据库这么大的压力?是不是慢查询?能不能加缓存?是不是要做分库分表?短期内做一些数据完整性上的妥协是不是能快速降低压力?
你们做了压力测试但是没有找到问题,也没有提出解决方案。
从缓解数据库的压力来说,加 redis 做缓存可以快速解决问题但是最好预热数据,否则一到点并发大了依然会崩,最终可能还是要走向 sacle out 的分库分表。

scale up 和压测的路子都是对的,但是问题没找准,解决方案也就出不来。
awanganddong
2022-05-26 11:39:10 +08:00
我们虽然调大了服务器的配置,但调大以后压测 10 分钟 20 万人和 4000 医护在线,服务器承载 20%都上不去,但前端页面会变得非常慢,基本上 10 几秒才能打开

关于这点,你们可以把 web 服务器放到单独的服务器上边,前置一个负载均衡,然后你们就查看外网带宽的负载情况,不够就加带宽。然后就是静态资源放到 oss 上边加 cdn 。

尽量把前后端拆分开来,这样的话,职权更清晰,更容易排查问题。

善用日志,负载均衡有日志,第三方 oss 也是有监控日志的,分析下就定位问题了。
Rache1
2022-05-26 11:44:26 +08:00
🤦‍♂️ 虽然很多人推荐 laravel-s 和 laravel-swoole ,但是还是鉴于目前的情况不建议赶鸭子上架,后续可以考虑再往这方面靠拢,包括 octane ,赶鸭子上架的话,你可能就有 1+N 个问题了。

现阶段可以根据各方面的慢日志:FPM 、MySQL 、Redis ,以及 Nginx 的日志来分析具体可能是哪些方面导致的问题。
encro
2022-05-26 11:48:22 +08:00
阿里云服务器连接数没有改吧,默认 5000 不够,
关键是 redis 和 mysql 要开持久链接。
PHP 一个 fpm 默认只能服务一个请求。
edk24
2022-05-26 11:49:38 +08:00
有没有开启 opcache, 这个扩展可以极大的优化性能, 如果是 php-fpm 造成大量占用 cpu 的话可以解决一定的问题

还有 php-fpm 的性能配置, 优化的话可以极大的压榨性能;


接口复杂不, 不复杂其实还蛮推荐用 swoole 重写的, 有数据库连接池, 可以降低 mysql 的压力. 因为每个请求都会生成一个数据库连接. 连接池可以解决这个问题, 速度提升很明显. 少了连接和关闭的操作

---

另一个是 swoole 支持协程, 这个东西也是可以降低数据库压力, 可以让占用数据库连接的时间变短, 提升连接池的复用率

---

慢 sql 要查, 看看有些表字段是不是没加索引, 性能影响很拉胯的

---

redis 集群要用起来, 耗时长的任务不要阻塞等待了, 改成异步查结果. 用 kafka 或者 rabbitmq 做延迟任务处理.

(延迟任务这一块参考支付宝提现, 他会告诉你转账中. 倒计时 5 4 3 2 1, 然后再给你结果)


我能想到只有那么些
encro
2022-05-26 11:55:41 +08:00
《解决 nginx+php/java/go/python+mysql 下 time_wait 连接数过多问题》

https://c4ys.com/archives/1609

'enableSchemaCache' => true,
'attributes' => [
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_TIMEOUT => 1,
],

《 php redis 连接数过多解决办法( Yii,predis,phpredis 等)》

https://c4ys.com/archives/2421

'redis' => [
'class' => 'yii\redis\Connection',
'socketClientFlags' => STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT,
],
encro
2022-05-26 12:03:00 +08:00
先看数据库 CPU ,
如果数据库 CPU 高,看数据库慢日志并优化索引,
如果数据库压力不高,看 WEB 服务器 PHP-FPM 日志,开启慢日志,优化慢方法,一般是循环太多或者调用第三方接口耗时。
查看连接数,使用持久链接,减少建立链接开销。
fkdtz
2022-05-26 12:03:17 +08:00
数据库的 CPU 都打满了?是不是一次性数据量处理太多了,有些数据被重复处理了?
fkdtz
2022-05-26 12:05:01 +08:00
在模拟环境装个 APM 看看调用慢在应该能直观反映问题,比如 tideways ,或者基于 tideways 的 php-monitor ,都可以统计出调用栈即调用耗时。
konakona
2022-05-26 12:05:20 +08:00
单纯就单体框架的性能排行榜而言,laravel 是几乎垫底的呀。怎么会选择它? lumen 都好那么一丢丢啊(因为前后分离)。

这种要 swoole 起步。
fkdtz
2022-05-26 12:07:38 +08:00
再看下 SQL 慢查呢,既然用了阿里云,他只带有慢 SQL 审计的,后面情况中服务器压测上不去,排除一下 DB 拖慢的可能性。

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

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

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

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

© 2021 V2EX