您的位置:首页 > 其它

老李分享:性能优化的境界2

2015-12-11 15:13 302 查看
了解到这里,再给出这样几个常见问题定位的场景: 第一类:请求无响应,浏览器始终处于等待状态。定位方法:kill -3或者jstack先分析线程堆栈,找到当前block的线程。常见于:外部接口调用无返回或者网络IO阻塞无响应;死锁;死循环;……。 第二类:宕机,进程挂掉。定位方法(这一类问题普遍比较难定位): (1)寻找hs_err_pidxxx.log这样的JVM日志 (2)使用JVM参数在JVM crash时写入到dump文件中 (3)catalina.out中寻找最后的日志 (4)宕机前环境数据采集常见于:JDK bug(数次遇到过JIT引起的这一类问题);调用dll的问题;…… 第三类:请求响应时间长。定位方法:kill -3或者jstack先分析线程堆栈,看线程大都停留在什么操作上面,再细化分析。常见于: 内存不足,可见到连续的Full GC;网络拥塞;LoadRunner等压力客户端瓶颈;数据库瓶颈,可进一步分析DB快照;…… 第四类:TPS低;TPS逐渐降低;TPS振荡幅度过大。定位方法(这一类问题最常见,定位的方法也最复杂):首先观察在压力增大时,CPU使用率能否上去,如果不能上去,寻找其他瓶颈:网络/内存/磁盘/……;CPU使用率上去了,观察在无压力时,是否有背景CPU使用(例如有后台定时任务线程消耗了大量CPU资源),如果没有,那可以尝试JProfiler等工具结合线程分析、业务分析,寻找热点。常见于:其他业务线程干扰;内存泄露;连接句柄用完;缓存命中率低下…… 好,暂时说到这里,下面来看第二重境界。达到这重境界意味着已经能够跳出“事后优化”的局限了,在设计和编码的过程当中,能够正式和全面地考虑性能的因素,比如: 减少使用时间敏感的容器管理,而使用容量或数量敏感的容器管理。比如我往一个缓冲里面存放若干数据,一种设计是每10分钟flush入库一次,还有一种设计是数据到达10M大小的时候flush入库一次,通常情况下,你觉得哪个方案更可靠?

线程的统一管理使用。我的经验是,10次对线程创建或者线程池的使用,往往就有5次是会出问题的。

避免使用同步Ajax。同步Ajax会造成浏览器假死,直至响应返回。

分析对同步、锁的使用。即便在一些有名的开源库中,我们也不止一次发现过不合理的同步设计,N多数据,单一的全局同步块(这是一种性能设计层面上的“中心化”),结果它就成为了瓶颈,改动还不容易下手,很麻烦。

对于不成熟的团队,建议能安排有经验的程序员把关设计文档和编码中的性能问题,把常见的问题列出来参考学习。 达到第二重境界还有一个明显的特征,就是在软件流程的前中期就开始做性能目标的论证和性能问题的验证: 性能切面分析。这指的是在系统设计初期,为了评估一个系统的性能表现,做出一个性能类似的系统原型,并对其做性能测试和评估,这时候因为性能问题而涉及到方案的变更,影响较小。据我所知,能够做到这一点的项目极少。在大多数团队中,依赖于架构师和掌握话语权的设计者依靠经验来避免性能问题带来的大的方案变更(或者,干脆摔一次跤,再进行痛苦的“重构”)。

性能的自动化测试验证。这一步必须伴随着Coding进行才有较大的意义,以便尽早发现性能问题。

设计和代码层面的评审。其实功能问题考虑得多、暴露得早,真正有危险的往往都是那些被忽视的非功能性问题,比如性能问题。

最后是第三重境界。达到这重境界的团队能够在早期规划构想阶段就将性能作为一个必备因素包含在内,这可不是随口说说的经验的估计,而是要有数据驱动的理论设计,比如做性能建模,根据市场大小、业务量、服务等级等等计算出性能的具体指标,并且在此要求下做合理的架构设计。 这里涉及的东西有很多,除了数据,还需要有大量的思考,对于一个网站来说,不妨问问如下的问题: 数据量会有多大,我该设计什么样的存储?一致性的要求又如何?

实时性要求是怎么样的?用户可以接受多少时间的数据延迟?

网站需要考虑到什么程度的可伸缩性?

哪些流程的数据处理有性能风险,数据量是什么级别的?怎么解决这个问题?

主要的业务时间消耗是怎样的,我需要设计怎样的业务流来满足?

所有的性能问题和其他一切非功能性问题一样,都是一定程度上的trade off,所以越优秀的设计者越需要思考,来规划这些问题的解决方案,在规划中因为性能问题而涉及到的因素有哪些,太多太多了。而要解决这样在规划中就预料到的性能问题,也有许多内容值得讨论,下面列出一些供参考: 1、集群组网:这是最基本的横向扩展的方式,把单节点的压力通过负载均衡分担到多个节点下,提高了系统负载能力的同时,亦提高了稳定性。

2、反向代理:一个大型的互联网网站不能不引入反向代理对静态资源的处理,Servlet容器用来处理静态图像和文本是非常奢侈的,Apache、Nginx、Squid都是优秀的解决方案。

3、页面静态化:互联网应用“缓存为王”,这可能是数种方案中能带来惠利最明显的一种,通过静态页面的生成和访问,有效地降低了系统负载。Web2.0的应用缓存命中率通常要稍差。

4、数据库优化:用户的访问难以满足了,数据库硬件设备的强化以外,从最基本的拆表、SQL调优,到纵向和横向的分库几乎成为必不可少的解决办法,或者更换廉价存储解决方案,使用NoSQL数据库等等。

5、CDN:CDN指的是内容分发网络,通过网络的广域层面对用户需求的分担,避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,提高用户体验。

6、分布式存储:海量信息的爆炸,需要廉价存储的解决方案,Web2.0的数据尤甚。分布式存储系统可以保证大吞吐量的数据读写和海量数据存储,实时性就显得不那么重要了。

7、数据缓存:这里的数据缓存和页面缓存区分开,数据缓存通常包括持久层层面的缓存和外部接口调用的缓存,数据缓存可以减小各类I/O调用,增加用户响应的平均时间。

8、功能性集群:初步的集群是对等的,这类集群方式简单可控;但是随着产品日益复杂化,用户访问压力日益增大,单纯的对等集群解决不了所有的问题,且产生大量冗余处理逻辑,使用功能性集群可以将完成不同功能的节点规约在一起。

9、页面分区:对一个大型网站,这是必不可少的。目的就是要进行页面静态化,并将动态和静态的区域分离开,以便在用户访问的时候,只做简单的聚合操作。

10、页面片段的生成和页面的聚合相剥离:许多频繁访问的相对静态的页面片段通常只需要的定时或事件触发的情况下才生成一次,甚至可以放在系统压力较轻的夜间生成。用户每次请求时只需要将静态的页面片段聚合成一个完整的页面(亦需要添加上动态的部分)即可。

11、隔离:对复杂系统的隔离和备份主要是为了解决稳定性问题,保持每一个单元的“简单”,化整为零,更容易将单元独立开发、产品化。

12、聚合方式的改进:引入高性能的服务端页面聚合方式(经过验证,常规SSI、ESI的性能存在缺陷);甚至客户端聚合:将展示模板送到客户端,再通过Ajax请求将JSON(或其它简单格式)数据流送到客户端,在客户端使用Ajax聚合出最终的页面来,好处在于将服务端的压力分担到客户端。

13、组件服务化:服务化的好处在于易于将组件的处理并行化,增加整体的响应速度。模式可以遵循SOA的方式,系统中使用高性能的ESB来进行服务编排和任务分派。

要达到第三重境界还要能够预测性能问题。这就需要成熟的监控体系,监控系统的变化,尽快做出反应。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  软件测试开发