代码从业者的一次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是搜索爬虫;

  同时,在 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!

  在高峰时段对 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就这样了。

时间: 2025-01-07 14:34:22

代码从业者的一次php应用优化实践的相关文章

网页设计与开发-网页设计,有一段代码太冗长了,求帮忙优化下!!!感激不尽!!!

问题描述 网页设计,有一段代码太冗长了,求帮忙优化下!!!感激不尽!!! 在最底下的那一段script代码太冗长了,求帮忙优化下,感激不尽!!! 以下是己完成的代码: <!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> </head> <style> .explain_box{ float:lef

《OpenACC并行程序设计:性能优化实践指南》一 2.1 测试代码:共轭梯度法

2.1 测试代码:共轭梯度法 本章中使用共轭梯度法作为标准测试代码.共轭梯度法是一种迭代算法,常用来逼近一组线性方程组成的大型稀疏系统.由于这种系统通常规模庞大,因此难于使用直接法进行求解.阅读本章不需要理解共轭梯度法的数学含义.提供了共轭梯度法的C和Fortran编码实现供读者参考.简洁起见,本章仅展示了C代码.不过不必担心,C代码的应用方式可以扩展到Fortran代码,两者区别不大.本章使用的代码遵循Apache许可,版本2.0.详情请阅读许可文件. 示例代码包含两种数据结构.第一个是向量结

数据库优化实践:索引篇

你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错, 但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了 留住用户,你开始着手调查访问变慢的原因. 经过紧张的调查,你发现问题出在数据库上,当应用程序尝试访问/更新数据时,数据库执行得相当慢 ,再次深入调查数据库后,你发现数据库表增长得很大,有些表甚至有上千万行数据,测试团队开始在生 产数据库上测试,发现订单提交过程需要花5分钟时间,但在网站上线前的测试中,提交一次订单只

数据库优化实践:TSQL篇

在前面我们介绍了如何正确使用索引,调整索引是见效最快的性能调优方法,但一般而言,调整索引 只会提高查询性能.除此之外,我们还可以调整数据访问代码和TSQL,本文就介绍如何以最优的方法重构 数据访问代码和TSQL. 第四步:将TSQL代码从应用程序迁移到数据库中 也许你不喜欢我的这个建议,你或你的团队可能已经有一个默认的潜规则,那就是使用ORM(Object Relational Mapping,即对象关系映射)生成所有SQL,并将SQL放在应用程序中,但如果你要优化数据访 问性能,或需要调试应用

实例jie如何提高Java Web 服务性能优化实践

本文介绍如何提升 Java Web 服务性能,主要介绍了三种方法:一是采用 Web 服务的异步调用,二是引入 Web 服务批处理模式,三是压缩 SOAP 消息.重点介绍在编程过程中如何使用异步 Web 服务以及异步调用和同步调用的差异点.本文还示范了如何在项目中使用以上三种方法,以及各种方法所适合的应用场景. Java Web 服务简介 Web 服务是一种面向服务架构的技术,通过标准的 Web 协议提供服务,目的是保证不同平台的应用服务可以互操作.Web 服务(Web Service)是基于 X

淘宝首页性能优化实践

想必很多人都已经看到了新版的淘宝首页,它与以往不太一样,这一版页面中四处弥散着个性化的味道,由于独特的个性化需求,前端也面临各方面的技术挑战: 数据来源多 串行请求渲染一个模块 运营数据和个性化数据匹配和管理 数据兜底容灾 本次淘宝首页改版,虽已不再支持 IE6 和 IE7 等低版本的古董浏览器,但依然存在多个影响首页性能的因素: 依赖系统过多,数据的请求分为三块,其一是静态资源(如 js/css/image/iconfont 等):其二是推到 CDN 的静态数据(如运营填写的数据.前端配置信息

【干货】手机QQ及Qzone速度优化实践

作者介绍: 黄浩宇 现就职于腾讯社交网络运营部,负责SNG社交网络业务移动类产品的业务运维工作,如QQ.Qzone业务优化及开发. 此前任职于阿里巴巴,负责天猫商城活动类业务的运维工作,如天猫双11,天猫周年庆等. 导语 移动互联网发展那么快,运维技术也要适应业务的变化啊,这次小编找了腾讯牛人介绍的手机QQ和手机Qzone的速度优化实践. 我们坚信不同垂直领域的运维分工会越来越不同,如何能在不同的业务形态上,利用运维技术和数据为业务带来更大的价值,将是我们下一步探索的重点方向. 1. 关于用户等

成功莫问出处:网站优化实践出真知

网站建设制作抑或网站优化可能一些人说起来头头是道,然而自身排名却依旧半死不活.很多站长在网站优化方面无法做到突出,所以导致排名上不去,无奈之下只可以将网站交给别人来优化.然而选用SEOer用人不当更易易造成网站的致命性灾难,因此在网上充斥着大量SEO优化方面的教程,以供站长学习.有句话叫"授人以鱼,不如授人以渔,"因此我们孜孜不倦的学习着网站优化的方法,以提高自身能力,可以在SEO优化方面独当一面.然而久而久之,站长养成了一个习惯:纸上谈兵,类似站长网每天有着大量技术型文章点缀其中.但

CDN HTTPS解决方案及优化实践

2017在线技术峰会,阿里云CDN技术专家容恪来为大家解析CDN HTTPS 红包背后的技术实践.本文主要从SSL/TLS 及 HTTP/2开始谈起,着重分析了HTTPS 架构和优化实践,最后对用户如何更好使用 HTTPS作了指导.   以下是精彩内容整理: SSL/TLS及HTTP/2介绍 HTTPS 对于HTTPS,其实是在HTTP 之下增加了 SSL/TLS的传输.在整个TCP/IP协议中的结构如图,传输层之上是会话层,会话层中传输的是SSL/TLS协议,HTTP 是在应用层.如果不用 S