Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >记一次 PHP 并发性能调优实战 -- 性能提升 104%

记一次 PHP 并发性能调优实战 -- 性能提升 104%

作者头像
猿哥
发布于 2020-04-26 07:05:14
发布于 2020-04-26 07:05:14
2.4K00
代码可运行
举报
文章被收录于专栏:Web技术布道师Web技术布道师
运行总次数:0
代码可运行

作者: 万千钧(祝星)

适合阅读人群

文中的调优思路无论是 php, java, 还是其他任何语言都是用. 如果你有 php 使用经验, 那肯定就更好了

业务背景

框架及相应环境
  1. laravel5.7, mysql5.7, redis5, nginx1.15
  2. centos 7.5 bbr
  3. docker, docker-compose
问题背景

php 已经开启 opcache, laravel 也运行了 optimize 命令进行优化, composer 也进行过 dump-autoload 命令.

首先需要声明的是, 系统的环境中是一定有小问题的(没有问题也不可能能够提升如此大的性能), 但是这些问题, 如果不通过使用合适的工具, 可能一辈子也发现不出来.

本文关注的就是如何发现这些问题, 以及发现问题的思路.

我们首先找到系统中一个合适的API或函数, 用来放大问题.

这个 api 设计之初是给 nginx 负载均衡做健康检查的. 使用ab -n 100000 -c 1000 进行压测, 发现 qps 只能到 140 个每秒.

我们知道 Laravel 的性能是出了名的不好, 但是也不至于到这个程度, 从 api 的编写来看不应该这么低. 所以决定一探究竟.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public function getActivateStatus()
 {
 try {
            $result = \DB::select('select 1');
            $key = 1;
 if ($result[0]->$key !== 1) {
 throw new \Exception("mysql 检查失败");
 }
 } catch (\Exception $exception) {
            \Log::critical("数据库连接失败: {$exception->getMessage()}", $exception->getTrace());
 return \response(null, 500);
 }
 try {
 Cache::getRedis()->connection()->exists("1");
 } catch (\Exception $exception) {
            \Log::critical("缓存连接失败: {$exception->getMessage()}", $exception->getTrace());
 return \response(null, 500);
 }
 return \response(null, 204);
 }
问题表现以及排查思路
# top

top 命令发现系统 CPU 占用 100% 其中用户态占 80%, 内核态占 20%, 看起来没什么大问题. 有一个地方看起来很奇怪, top 命令的运行结果

就是有一部分 php-fpm 进程处在 Sleep 状态, 但 CPU 占用还是达到了近 30%. 当一个进程处于 Sleep 状态的时候, 任然占用了不少 CPU, 先不要怀疑是不是进程的问题, 我们看一下 Ttop 命令的 man page.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
%CPU -- CPU usage
The task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.

大致意思是这个占用是最后一次屏幕刷新的时候, 进程 CPU 的占用. 由于 top 命令收集信息的时候, 可能 linux 把这个进程强制调度了 ( 比如用于 top 收集进程信息 ), 所以在这一瞬间(屏幕刷新的这一瞬间)某些 php-fpm 进程处于 sleep 状态, 可以理解, 所以应该不是 php-fpm 的问题.

pidstat

首先选出一个 php-fpm 进程, 然后使用 pidstat 查看进程详细的运行情况

过程中也没发现什么异样, 并且和top命令的运行结果也基本一致.

vmstat

保持压测压力, 运行 vmstate 查看, 除了 context switch (上下文切换)有点高之外, 并没有看到太多异常. 由于我们使用的 docker, redis, mysql 都运行在同一台机器上, 7000 左右的 CS 还是一个合理的范围, 但是这个 IN(中断)就有点太高了, 达到了 1.4 万左右. 一定有什么东西触发了中断.

我们知道中断有硬中断和软中断, 硬中断是由网卡, 鼠标等硬件发出中断信号, cpu 马上停下在做的事情, 处理中断信号. 软中断是由操作系统发出的, 常用于进程的强制调度.

不管是 vmstat 还是 pidstat 都只是新能探测工具, 我们无法看到具体的中断是由谁发出的. 我们通过 /proc/interrupts 这个只读文件中读取系统的中断信息, 获取到底是什么导致的中断升高. 通过 watch -d 命令, 判断变化最频繁的中断.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
watch -d cat /proc/interrupts

我们发现其中 Rescheduling interrupts 变化的最快, 这个是重调度中断(RES),这个中断类型表示,唤醒空闲状态的 CPU 来调度新的任务运行。这是多处理器系统(SMP)中,调度器用来分散任务到不同 CPU的机制,通常也被称为处理器间中断(Inter-Processor Interrupts,IPI)。结合 vmstat 中的命令, 我们可以确定造成 qps 不高的原因之一是过多的进程争抢 CPU 导致的, 我们现在还不能确定具体是什么, 所以还需要进一步的排查.

strace

strace 可以查看系统调用, 我们知道, 当使用系统调用的时候, 系统陷入内核态, 这个过程是会产生软中断的, 通过查看 php-fpm 的系统调用, 验证我们的猜想

果然, 发现大量的 stat 系统调用, 我们猜想, 是 opcache 在检查文件是否过期导致的. 我们通过修改 opcache 的配置, 让 opcache 更少的检查文件 timestamp, 减少这种系统调用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    opcache.validate_timestamps="60"    opcache.revalidate_freq="0"

再次执行 ab 命令进行压测

果然 qps 直接涨到了 205, 提升非常明显, 有接近 46% 的提升

perf

现在任然不满足这个性能, 希望在更多地方找到突破口. 通过

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
perf record -gperf report -g

看到系统的分析报告

我们看到, 好像这里面有太多 tcp 建立相关的系统调用(具体是不是我还不清楚, 请大神指正, 但是看到 send, ip, tcp 啥的我就怀疑可能是 tcp/ip 相关的问题). 我们怀疑两种情况

  1. 与 mysql, redis 重复大量的建立 TCP 连接, 消耗资源
  2. 大量请求带来的 tcp 连接

先说第一个, 经过检查, 发现数据库连接使用了 php-fpm 的连接池, 但是 redis 连接没有, redis 用的 predis, 这个是一个纯 PHP 实现, 性能不高, 换成了 phpredis:

打开 laravel 的 config/database.php 文件, 修改 redis 的 driver 为 phpredis, 确保本机已安装 php 的 redis 扩展. 另外由于 Laravel 自己封装了一个 Redis 门面, 而恰好 redis 扩展带来的对象名也叫 Redis. 所以需要修改 Laravel 的 Redis 门面为其他名字, 如 RedisL5.

再次进行压测

达到了喜人的 286qps, 虽然和其他主打高性能的框架或者原生 php 比, 还有很高的提升空间(比如 Swoole), 但是最终达到了 104% 的提升, 还是很有意义的

总结

我们通过 top, 发现系统 CPU 占用高, 且发现确实是 php-fpm 进程占用了 CPU资源, 判断系统瓶颈来自于 PHP.

接着我们通过 pidstat, vmstat 发现压测过程中, 出现了大量的系统中断, 并通过 watch -d cat /proc/interrupts 发现主要的中断来自于重调度中断(RES)

通过 strace 查看具体的系统调用, 发现大量的系统调用来自于 stat, 猜测可能是opcache 频繁的检查时间戳, 判断文件修改. 通过修改配置项, 达到了 46% 的性能提升

最后再通过 perf, 查看函数调用栈, 分析得到, 可能是大量的与 redis 的 TCP 连接带来不必要的资源消耗. 通过安装 redis 扩展, 以及使用 phpredis 来驱动 Laravel的 redis 缓存, 提升性能, 达到了又一次近 50% 的性能提升.

最终我们完成了我们的性能提升 104% 的目标

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PHP技术大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux性能优化实战 笔记
平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
OwenZhang
2021/12/08
1.8K0
Linux性能优化实战 笔记
Linux 性能优化的全景指南,可能都在这里了,建议收藏~
性能问题的本质就是系统资源已经到达瓶颈,但请求的处理还不够快,无法支撑更多的请求。性能分析实际上就是找出应用或系统的瓶颈,设法去避免或缓解它们。
用户6543014
2022/03/04
2.7K0
Linux 性能优化的全景指南,可能都在这里了,建议收藏~
记一次生产环境的性能分析过程
本文主要记录了一次生产环境后台服务的性能分析过程,通过结合多种性能分析工具定位出系统的性能瓶颈并给出优化方案,将整个过程记录并总结如下。
用户6980797
2024/05/26
1360
​Linux CPU 性能优化指南
本文作者:allenxguo,腾讯 QQ 音乐后台开发工程师 本文主要帮助理解 CPU 相关的性能指标,常见的 CPU 性能问题以及解决方案梳理。 系统平均负载 简介 系统平均负载:是处于可运行或不可中断状态的平均进程数。 可运行进程:使用 CPU 或等待使用 CPU 的进程 不可中断状态进程:正在等待某些 IO 访问,一般是和硬件交互,不可被打断(不可被打断的原因是为了保护系统数据一致,防止数据读取错误) 查看系统平均负载 首先top命令查看进程运行状态,如下: PID USER
腾讯技术工程官方号
2020/08/11
8.8K0
性能调优|成都核酸系统篇
先来吃个瓜,最近成都核酸检测系统挂了,发文称经受了上海每小时600w次峰值考验,算下来QPS不足1700,看到这文章就是在找骂,吃瓜群众不要急着骂人,因为这文章压根就不是写给你们这些技术专家看的。
用户5166556
2023/03/18
6600
性能调优|成都核酸系统篇
PHP码农在Golang压力下的生存之道-PHP性能优化实践
随着国内Golang的火爆,phper的生存压力越来越大,在一次内部技术讨论中,gopher甚至提出,要什么php,写php的全部开掉,唉,码农何苦为难码农。 本文试图寻找一种有效实践,减少php web程序和golang之间的性能差距,摆脱php在公司往后只能写后台的悲惨命运。 做优化的思路 1、了解php语言特性 2、了解php的执行过程 3、压测分析性能 语言特性 PHP被称为脚本语言或解释型语言,它没有被直接编译为机器指令,而是编译为一种中间代码的形式,无法直接在CPU上执行。 所以PHP的执行需要
架构师刀哥
2018/03/20
2.4K0
记一次java应用性能调优
在项目压测过程中,发现系统占用,上下文切换非常频繁,在此记录下调优过程,希望对后来人有所帮助。
良月柒
2019/03/19
7040
中间件业务在网易轻舟容器平台的性能调优实践
随着业务容器化的推进,经常有客户抱怨应用 QPS 无法和在物理机或者云主机上媲美,并且时常会出现 DNS 查询超时、短连接 TIME_OUT、网络丢包等问题,而在容器中进行调优与诊断的效果因为安装工具的复杂度大打折扣。本文基于网易轻舟中间件业务容器化实践,总结容器场景下的性能调优心得,供读者参考。
深度学习与Python
2020/09/29
5560
中间件业务在网易轻舟容器平台的性能调优实践
超高性能可扩展HTTP服务框架 Webman
webman是一款基于workerman开发的高性能HTTP服务框架。webman用于替代传统的php-fpm架构,提供超高性能可扩展的HTTP服务。你可以用webman开发网站,也可以开发HTTP接口或者微服务。
Tinywan
2023/09/06
1.9K0
超高性能可扩展HTTP服务框架 Webman
nginx+php-fpm故障排查
小明初到一家公司做运维的工作,刚来的第一天就开始部署LNMP(Linux+Nginx+MySQL+PHP)环境,结果出现了问题。 他来向我请教。
田帅萌
2018/09/14
2.2K0
nginx+php-fpm故障排查
性能分析(3)- 短时进程导致用户 CPU 使用率过高案例
并发 100 个请求测试 VM1 的 Nginx 性能,总共测试 1000 个请求
小菠萝测试笔记
2020/08/11
1.5K0
性能分析(3)- 短时进程导致用户 CPU 使用率过高案例
一次性能优化经历
自从上次修改backlog之后, Silly的IO能力,就一直以少量(约4~6K)的差距落后于redis,却一直找不到原因。
重归混沌
2020/04/26
3950
技能篇:linux服务性能问题排查及jvm调优思路
只要业务逻辑代码写正确,处理好业务状态在多线程的并发问题,很少会有调优方面的需求。最多就是在性能监控平台发现某些接口的调用耗时偏高,然后再发现某一SQL或第三方接口执行超时之类的。如果你是负责中间件或IM通讯相关项目开发,或许就需要偏向CPU、磁盘、网络及内存方面的问题排查及调优技能
潜行前行
2022/04/26
8570
技能篇:linux服务性能问题排查及jvm调优思路
常用Linux命令 (一)
第一行中,03:30:22是当前时间,up 39 min是系统运行的运行了多长时间,1 user指出了当前有几个用户登录到系统,load average指的是系统负载,这后面的三个值分别是1分钟,5分钟,15分钟的系统负载平均值。
用户2131907
2019/02/27
1.5K0
PHP-FPM 性能配置优化
php-fpm 全称是 PHP FastCGI Process Manager 的简称,从名字可得知,是一个 FastCGI 的管理器。
南山竹
2024/06/12
2220
PHP-FPM 性能配置优化
某个应用的 CPU 使用率居然达到 100%,我该怎么办?
通过前两节对平均负载和 CPU 上下文切换的学习,我相信你对 CPU 的性能已经有了初步了解。不过我还是想问一下,在学这个专栏前,你最常用什么指标来描述系统的 CPU 性能呢?我想你的答案,可能不是平均负载,也不是 CPU 上下文切换,而是另一个更直观的指标—— CPU 使用率。
米开朗基杨
2019/08/29
2.4K0
某个应用的 CPU 使用率居然达到 100%,我该怎么办?
为什么要推荐使用现代化PHP框架?
PHP语言从1995年发布,至今已经有29多年的历史,在期间涌现了成千上万的MVC框架,大致可以将其分为以下三大类:
Tinywan
2024/06/18
2320
为什么要推荐使用现代化PHP框架?
Linux 性能调优之CPU调优认知
对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》
山河已无恙
2025/04/09
7441
Linux 性能调优之CPU调优认知
linux性能优化心得
本文以 极客时间 倪鹏飞老师的专栏为基础进行的编写心得、由于本人水平有限,如果有什么不妥的地方,还请各位批评指正。
怀朔
2022/05/25
8880
使用OPCache提升PHP的性能
对于 PHP 这样的解释型语言来说,每次的运行都会将所有的代码进行一次加载解析,这样一方面的好处是代码随时都可以进行热更新修改,因为我们不需要编译。但是这也会带来一个问题,那就是无法承载过大的访问量。毕竟每次加载解析再释放,都会增加 CPU 的负担,通常一台 8核16G 的服务器在2、3000并发左右 CPU 就能达到60%以上的使用率。而且如果你使用的是类似于 Laravel 这种大型的框架,效率将更加低下。这个时候,我们通常会通过增加服务器数量来做负载均衡,从而达到减轻服务器压力的效果。不过,这样做的成本又会增加许多。那么,有没有什么优化的方案呢?
硬核项目经理
2020/08/13
1.1K0
相关推荐
Linux性能优化实战 笔记
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验