我的架构经验系列文章 - 后端架构 - 性能层面

回到索引 http://www.cnblogs.com/lovecindywang/archive/2012/12/23/2829828.html

 

性能层面:

  • 性能分析

我觉得性能分析的话要注意几个要点:

  1. 不要去猜:对于自己写的代码你是否知道你的代码要执行多久,是不是还在用时间相减来测试代码执行时间?现在有很多自动化的工具可以在程序运行的时候,测试代码中每一句语句的执行时间,可以有效分析出代码的性能瓶颈。对于比较重要的业务逻辑建议采用类似的工具来进行性能分析,有的时候性能慢的代码不一定是自己写的还可能是框架内提供的,如果没有一个丰富的编码经验是不太可能知道这些点的,但是通过这样的分析工具你就能知道这个地方会慢,虽然框架的代码我们不能改,但是我们可以进行缓存或者是可以换一种方法写。打个比方你可能认为获取当前机器的名字是很快的操作,但如果框架内部通过一定的操作系统接口访问这个操作需要5毫秒的话就很夸张了,很可能这个操作在你整个请求中运行了10次获取了10次机器名,那么不知不觉50毫秒就耗去了,这个时候你还以为是数据库慢,这就永远找不到问题所在了(解决就相对简单了只要缓存机器名就好了)。因此,除了加点方式来测算代码性能,更科学的是采用一些工具来测算,或许这个工具本身就是通过植入无数个加点代码来实现这种测算,但这总比自己一次又一次手动改代码来的好。总而言之,有一些性能问题不是你自己写代码引起的,或者是外部代码或者是框架内的代码,猜是猜不出来的。
  2. 注意区分优先级:一般我们可以认为硬件由CPU、内存和IO构成,其中IO分网络和磁盘,不管是网络还是磁盘其性能是最差的也是最可能达到系统中性能瓶颈的地方,知道这一点我们就知道了性能分析的优先级了,忽略数据库层面、网络层面的问题把时间浪费和纠结在for/foreach的性能这种纯语言层面的东西则不是那么有效果。这里举几个例子典型的立竿见影的性能相关的例子,同时也可以反映出通过一定的手段看到问题而不是去猜是多么有效:
    • 遇到过在使用ORM的时候ORM是乐观并发机制的,把所有的字段的值都作为where条件传了过去,有一个表有近百个字段当然更新的效率低了,通过查看体积到数据库的SQL语句就可以查明这个问题,解决的办法是不把相关字段列入检查或采用悲观并发。
    • 遇到过在使用Memcached客户端的时候没有把应该作为静态单例的工厂对象作为单例而是每次使用都创建一遍,导致每次都会花2秒创建一个连接池,性能极其低下,而且导致占用了几万个网络端口,通过基本的操作系统命令检查磁盘网络相关的参数即可查明这个问题,解决的办法是把工厂单例。
    • 遇到过一个程序只运行几个小时就会占用到10GB内存导致崩溃,看代码无法查明问题,通过在运行性能监视工具检测虚拟机不久就可以查明问题,解决的办法是修复这个BUG。
    • 一个网站使用的模板每次都是从网络上获取的,导致每次请求其实都在服务端再发起一次请求到其它网站去下载页面然后再处理,性能极其低下秒并发只能在10左右。要查明这个问题其实不难,运行一次就耗时1秒,对模板进行缓存即可解决问题。

  3. 注意观察日志:对于很多组件(比如Mongodb),在其初始化的时候都会对系统基本的配置进行检测,如果发现因为某个配置不合理组件无法达到最优会给出提示,因此要注意这些组件的日志,以便及早发现性能问题。

 

  • 压力测试

虽然说某些工具可以帮助我们分析程序性能,但是有一些性能问题必定是在高压力下才会产生的。很典型的就是为了线程安全使用的锁,不管是程序层面的锁还是数据库层面的表锁行锁,锁意味着串行,串行意味着在压力增大的情况下压力越大排队越厉害越慢。当然,压力测试还可能测试出因为多线程环境带来的线程安全问题。系统整体的性能是受最差的那个点拖累的,如果系统各个模块抗压能力差距很大的话,压力测试比较容易测出问题。作为网站开发我们应该有意识,对于普通的服务器,一般每秒能处理多少请求,一般每秒数据库能处理多少操作,有一个熟练级的认识,如果你发现经过压力测试,Web服务器每秒最大只能处理10个并发,那么系统肯定存在性能问题的。压力测试不但可以测试出系统的问题,还可以测试出一定的硬件条件下,系统可以承受的最佳的访问人数在多少,低于这个人数系统跑不满,超过这个人数系统的响应走下坡路,根据这个结果可以有理有据去选择集群的数量。

 

  • 线上问题排查

对于已经在线上的代码不太可能去运行什么性能分析工具,因为这些通过这些工具执行的代码会比直接运行代码慢好几倍,在线上这么做可能导致网站直接崩溃。

  1. 简单的办法可以通过加点,然后把代码灰度部署到某些机器查看日志来分析原因。
  2. 或者还可以直接到某台机器抓取进程样本来做静态分析(特别适合有虚拟机的语言)。通过抓取一个进程的样本可以了解进程中哪些对象占用了绝大部分内存,垃圾回收各个区的状态来分析内存性能问题。通过抓取多个进程样本可以比较哪些线程耗时比较厉害,耗时厉害多线程主要集中在执行什么代码来分析CPU性能问题。
  3. 除了这种内在的分析办法还可以通过外部来分析,比如通过Fiddler之类的工具来观察慢是因为网络原因还是因为并发数的原因还是因为服务端的原因。比如通过数据库的监控工具来监控每一个SQL语句的执行时间抓出最慢的SQL。比如通过观察虚拟机的状态,观察操作系统的性能指标,观察Windows的性能计数器等可以帮助判断大概存在的性能问题。

 

 

posted @ 2012-12-23 18:01 lovecindywang 阅读(...) 评论(...) 编辑 收藏