0

0

代码从业者的一次php应用优化实践

php中文网

php中文网

发布时间:2016-06-21 08:53:43

|

1195人浏览过

|

来源于php中文网

原创

   系统跑得时间长了,总会出现这样那样的问题和瓶颈,有了问题不可怕,我们有“打虎”的家伙事儿--无非就是定位问题->分析问题->提出解决方案->实践->结果反馈->总结再优化。

  之前做过的一次优化实践,最近翻出来看看,有些通用的优化手段还是可以复用的。系统跑得时间长了,总会出现这样那样的问题和瓶颈,有了问题不可怕,我们有“打虎”的家伙事儿--无非就是定位问题->分析问题->提出解决方案->实践->结果反馈->总结再优化。

  问题描述:系统采用 PHP5 + Zend framework 开发,在数据规模和访问量增加后(千万级),出现了后台apache服务器负载过高的现象,在访问高峰时段(比如每天下班到晚上10点这一段时间,特别是周五),机器CPU负载会飙升到170多,CPU负载过高造成处理请求也相应的变慢,所以亟需解决这个问题。

  问题分析:通过连续几天的观察和分析,当CPU使用率达到100%时,其中系统CPU使用率占据了很大的比例,用户CPU使用率倒不是很高,另外前端 haproxy 和 squid cache的cpu负载很低,memcached和squid的hit ratio一般都能达到60%左右。

  分析backend的access-log,发现相当大一部分请求的User-Agent是搜索爬虫;

立即学习PHP免费学习笔记(深入)”;

  同时,在 apache 上配置了xdebug,在空闲时段对主要的页面的测量了一组性能数据,通过使用kcachegrind对测得的数据进行分析(如何配置xdebug,可以用soso搜一下),发现:

  性能数据不够稳定,同样的请求之间测试数据会相差比较大

  慢的点比较分散

  memcached的访问大部分的情况都比较慢(100ms以上)

  解决方案通过上述初步的分析,对现有的程序逐步作了一系列调整。

  首先考虑到的是是否可以想办法增加前端squid cache的Hit ratio,从而减少穿透squid到达后端apache的请求数。

  考虑到相当一部分请求来源于Crawler,而之前squid cache只会对设置了language cookie的请求作cache,而来自Crawler的请求都没有cookie信息。于是想到把来自Crawler的请求都默认为language为zh_CN的,然后修改haproxy的配置,把User-Agent为常见的Crawler的请求都转交给squid cache.

  修改php代码,把一些页面的缓存时间设置得更长一些

  经过如上两个步骤,到达apache的请求确实减少了一些,但是这个对cpu负载过高的问题帮助很少,于是另寻它法。

  其次,根据使用 xdebug profiling的结果来看,和memcached的交互耗时比较长,于是想是否可以想办法让memcached能更快地响应请求,从而使得每一次请求能更快完成,从而使并发降低。

  通过代码分析,发现线上memcached使用的是poll(),而memcached的连接数在繁忙的时候保持在1000左右,memcached的CPU使用率在 30% 左右。很显然,poll()方式在处理如此多的并发连接时是很低效的。于是重新编译memcached,使其使用epoll()的方式来处理请求,替换为epoll之后,memcached的cpu usage从 30%左右降低到 3% 左右,10倍之多!

  另外,memcached的hit ratio不是特别高,而且被换出的item数也比较高,于是想到对cache的内容作partition.原本打算做 manually partition,后来发现php的最新的memcache扩展就能支持根据cache的key自动作partition,而且能在不修改程序代码(需要修改配置文件:-))的情况下增加新的memcached实例。于是升级每一个apache的php memcache扩展,然后再配置文件中增加了一台新的memcached。到此完成memcached的内容partition。修改之后的效果比较显著,页面的载入时间比修改前缩短了很多。

  经过这两步的调整,memcached的效率比以前高了,但是apache的负载仍然居高不下,没辙,再想其它办法!

  进一步深入分析前面说到主要系统CPU占用很高,要找原因只能深入内核了:) 从现在开始了我们的strace之旅。套用一句Nike的广告词:Just strace it!

新秀企业网站系统PHP版1.1 beta6
新秀企业网站系统PHP版1.1 beta6

新秀企业网站系统PHP版是一款简洁易用、方便二次开发的PHP企业网站系统。后台功能齐全,操作简便,可开启伪静态和纯静态模式,有利于SEO优化;前台可设置成同时显示多国语言,适合用于外贸企业建站;程序代码清晰简洁,可扩展性良好,安全可靠。新秀企业网站系统PHP版可免费下载使用,可用于商业用途,没有功能和时效限制,除版权标识外,所有代码都允许修改。后台功能简介:1.基本设置:基本信息,联系方式,网站设

下载

  在高峰时段对 httpd 进程进行了strace,方法不外乎如下这些

  strace -p PID -c 得出 summary

  strace -p PID -o output.log 写入文件,慢慢研究

  strace -p PID -e trace=file 只看 filesystem 操作相关的 syscalls

  strace -p PID -elstat64,stat64,open,getcwd 只跟踪这些 syscalls

  …

  从上述strace分析得到如下结论:

  lstat64,stat64,open等 syscalls实在是多啊

  上述 syscalls 占用时间确实不少! 60%以上的时间都被它们抢了, orz

  绝大多数 syscall 是失败的,真是屡败屡战啊

  有了上述数据,我们就找到了问题的方向了,那就是找这些毫无意义的系统调用是怎么来的。

  经过分析,这些是php要加载某一个类时,会去 include_path 中定义的一系列目录中搜寻该类对应的文件,挨个目录这么试过去,直到找到为止。嗯,这种方式显然是比较低效的,有没有更好的方式来完成这个事情呢?答案是肯定的,有!而且还有不止一种方法!

  调用require_once()时,参数写绝对路径(开始Guys write Zend Framework就不懂这个道理;后来才有更新))

  使用 __autoload()对class进行 lazy loading,也就是说真正需要的时候才去加载,而不是不管三七二十一把可能用到的类文件都require_once了。

  问题是找到了,但是要解决这个问题还面临着另一个问题。开发中代码都注意用绝对路径了,唯一可以改进的地方是改为 lazy loading,但是 Zend Framework中大量的require_once采用相对路径,这个就是导致问题——这里我说的问题是本文我们谈论的CPU负载过高的问题——的根本原因。

  OK,既然问题找到了,动手解决。写个脚本自动生成 Class -> File Path 对应关系,生成代码中所有类和Zend Framework中所有类的对应关系文件。把代码中和Zend Framework库中所有的 require_once 都注释掉。然后进行详细的测试,然后上线。结果令人吃惊,负载降到了 3 以内!!问题解决。

  总结:

  写代码的人都知道,可能出问题的地方总会出问题,任何问题都会有个原因(哪怕暂时没有找到),从根上解决才是王道,解决什么问题不重要,希望大家能学习这个解决的思路,善于利用工具。ok,这个case就这样了。




PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

797

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

272

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

144

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

25

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

92

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

53

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

15

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

717

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

64

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
深入剖析redis教程
深入剖析redis教程

共55课时 | 8.2万人学习

Memcached手册
Memcached手册

共0课时 | 0.1万人学习

韩顺平Memcached视频教程
韩顺平Memcached视频教程

共10课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号