前段时间,性能测试团队经历了一个规模较大的门户网站的性能优化工作,该网站的开发和合作涉及多个组织和部门,而且网站的重要性不言而喻,同时上线时间非常紧迫,关注度也很高,所以对于整个团队的压力也非常大。
在此,把整个经历过程给大家分享一下,包括了主要包括了如何使用性能测试的压测工具,压测前的性能问题评估,以及压测执行后的性能问题分析、瓶颈定位。
该门户网站的服务器是放在华通和阿里云的平台上的,所以对华通和阿里共建的云平台安全及应急措施方面要求非常高,需要团队给予全力的保障和配合。
性能测试(Performance Testing)是集测试机管理、测试脚本管理、测试场景管理、测试任务管理、测试结果管理为一体的性能云测试平台,可以帮助您全方位的评估云上系统性能。
本次优化主要是使用了该测试平台服务对客户搭建在ECS上的服务器进行多种类型(性能测试、负载测试、压力测试、稳定性测试、混合场景测试、异常测试等)的性能压测、调试和分析,最终达到满足期望预估的性能目标值,且上线后在高峰期满足实际的性能和稳定要求。
在介绍项目经历之前,再明确一下测试当中用到的专业指标术语定义,包括但不仅限于以下:
PV: 即PageView, 即页面浏览量或点击量,用户每次刷新即被计算一次。我们可以认为,用户的一次刷新,给服务器造成了一次请求。
UV: 即UniqueVisitor,访问您网站的一台电脑客户端为一个访客。00:00-24:00内相同的客户端只被计算一次。
TPS:TPS(Transaction Per Second)每秒钟系统能够处理的交易或事务的数量,它是衡量系统处理能力的重要指标。
响应时间: 响应时间是指从客户端发一个请求开始计时,到客户端接收到从服务器端返回的响应结果结束所经历的时间,响应时间由请求发送时间、网络传输时间和服务器处理时间三部分组成。
VU: Virtual user,模拟真实业务逻辑步骤的虚拟用户,虚拟用户模拟的操作步骤都被记录在虚拟用户脚本里。一般性能测试过程中,通俗称之为并发用户数。
TPS波动: 系统性能依赖于特定的硬件、软件代码、应用服务、网络资源等,所以在性能场景执行期间,TPS可能会表现为稳定,或者波动,抑或遵循一定的上升或下降趋势。我们用TPS波动系数来记录这个指标值。
CPU: CPU资源是指性能测试场景运行的这个时间段内,应用服务系统的CPU资源占用率。CPU资源是判断系统处理能力以及应用运行是否稳定的重要参数。
Load: 系统正在干活的多少的度量,队列长度。系统平均负载,被定义为在特定时间间隔(1m,5m,15m)内运行队列中的平均进程数
。
I/O: I/O可分为磁盘IO和网卡IO。
JVM: 即java虚拟机,它拥有自己的处理器、堆栈、寄存器等,还有自己相应的指令系统。Java应用运行在JVM上面。
GC: GC是一种自动内存管理程序,它主要的职责是分配内存、保证被引用的对象始终在内存中、把不被应用的对象从内存中释放。FGC会引起JVM挂起。
网速: 网络中的数据传输速率,一般以Byte/s为单位。通过ping延时来反映网速。
流量: 性能测试中,一般指单位时间内流经网卡的总流量。分为inbound和outbound,一般以KB为单位。
本次性能测试过程的参与人包括了阿里云应急保障小组等多部门人员,网站为外部供应商开发,阿里云提供云主机和技术支持。
该网站之前前期也由其他部门做了验收工作,进行了完整的性能测试,报告显示,性能较差,第一次测试,网站并发数没有超过35个,第二次测试,网站上做了优化后,静态页面缩小后,并发用户数100内 5s ,200内 90%响应在15s以上,随着并发用户数的增加,页面响应最高可到20多秒,而且访问明显感觉较慢,所以联系了阿里云的技术支持,希望能够帮助诊断性能问题,给出优化建议。
| 测试业务 | 并发用户数 | 平均响应时间(秒) | 90%响应时间(秒) |
|---|---|---|---|
| 首页浏览 | 100 | 12.082 | 15.289 |
| 200 | 23.949 | 29.092 | |
| 分页浏览 | 100 | 8.973 | 12.343 |
| 200 | 18.846 | 24.106 |
经过会议讨论后,评估出最终的测试目标:带页面的所有静态资源一起,响应时间必须小于5秒,同时并发访问用户数最低500,TPS根据实际的结果来得出。
通过性能测试前端分析工具(未开放)分析,页面的响应时间88%左右都是消耗在前端资源加载上,服务器端消耗只占到了页面响应的12%左右;

一个网站的响应一般由四部分时间组成,前端、网络、服务器和数据库,前端主要是减小页面大小,减小页面请求数,优化页面js等,网络主要是使用CDN,优化连接数等,服务器主要是优化Apache,优化Tomcat,优化java代码等,数据库是优化sql语句,优化索引,优化数据存储等。<rb>

我们对页面的优化仍然从前端开始,首先通过性能测试的前端测试工具(未开放)进行扫描,我们发现以下问题并优化:
一般核心页面都要求在300毫秒以下,非核心页面要求在500毫秒以下,同时重点关注并发时的负载和稳定,服务器端代码和响应的快速稳定是整个页面性能的重点。
根据前期需求评估的内容,客户是一个门户网站,主要由不同功能页面组成的,各个功能页面当中又包含了静态内容和异步动态请求,所以,性能测试的脚本的编写主要涵盖了各页面的请求和相关静态资源的请求,这里存在一个串行和并行的概念:
串行:请求的页面和页面当中的静态资源、异步动态请求组成一个同步请求,每一个内容都作为一个事务(也可以共同组成一个事务,分开事务的好处是可以统计各部分的响应时间),这样压测任务执行时,线程就会根据事物的顺序分布调用执行,相当于一个页面的顺序加载,弊端是无法模拟实际IE的小范围并发,但这样测试的结果是最严格的。
并行:各个页面之前可以使用不同的任务,采用并行的混合场景执行,同时设置一定的比例(并发用户数),保证服务器承受的压力与实际用户访问相似。
场景并发用户数:经常会遇到“设置多大并发用户数合适?”的问题,因为在没有任何思考时间的时候,我们有一个简单的公式:
VU(并发压测用户数) = TPS(每秒执行事务数) × RT(响应时间)
所以,在寻找合适的并发用户数上,建议使用性能测试的“梯度模式”,逐渐增加并发用户数,这个时候压力也会越来越大,当TPS的增长率小于响应时间的增长率时,这就是性能的拐点,也就是最合理的并发用户数;当TPS不再增长或者下降时,这个时候的压力就是最大的压力,所使用的并发用户数就是最大的并发用户数。如果此时的TPS不满足你的要求,那么就需要寻找瓶颈来优化。如下图演示的一个性能曲线:
注意:使用外网地址压测可能会造成瞬时流量较大,造成流量计费,从而产生费用,建议可以使用内网地址压测,避免损失。
在按照客户提供的4个URL请求构造场景压测以后,同时根据实际情况和客户要求,使用性能测试,构造相应的场景和脚本后,模拟用户实际访问情况,并且脚本中加上了img、js、css等各一个的最大静态资源:
分析和优化:

服务器资源消耗较高,超过75%,存在瓶颈,分析平台显示:

分析发现原来是apache到tomcat的连接等待导致,现象是100个并发压测,就有100个tomcat的java线程,而且全部是runnable的状态,轮询很耗时间。
同时发现用户使用的是http协议,非ajp协议,不过这个改动较大,需要使用mod_jk模块,时间原因, 暂缓。
解决方法:修改了Apache和tomcat的连接协议 为nio协议,同时去除ssl 协议。Tomcat连接数据库池由30初始调整为300,减少开销
<Connectorport="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" /> 性能对比:
发现机器的核数都是2核,8G内存,对于CPU达到98%的情况,CPU是瓶颈,而对于应用来说比较浪费,所以将2核统一升级为4核。
扩展机器资源,从目前的4台扩到6台,同时准备4台备份,以应对访问量较大的情况。
思考和风险:
找到几个页面的所有动态资源后,整合成为一个事务,串行访问,同时并发压测,从而对纯服务器端进行压测,测试结果如下图:

性能分析:页面一和页面二的响应时间分别达到了5秒和2秒,性能较差,整体TPS只有11
前端响应时间从5秒降低到150毫秒,前台TPS由150提升到1500.总的TPS可以达到2000。

通过性能测试模拟用户实际访问情况,包括所有静态资源,评估出当响应时间小于5秒的时候,最大支撑的并发用户数。

可以看到,所有的事务RT加起来小于5秒的情况下,并发用户数可以达到3000(6个事务,6个脚本,每个脚本500),远远满足项目500个并发用户的目标。

评估其他非主站应用的性能以及含静态页面的其他5个页面内容,包括:
测试结果:

发现的风险和问题:

按照JVM内存管理模式,调整系统启动参数,如果一台ECS部署一台服务器,建议不要选择默认的JVM配置,应该设置内存为物理内存的一半,同时设置相应的YTC和FGC策略,观察Old区变化,避免大量Full GC,建议Full GC频率大于1小时,同时GC时间小于1秒钟。

备注:服务器的CPU达到100% 这其实是一个好的现象,说明我们的逻辑全部已经走到了资源消耗上,而不是由外部其他逻辑限制或blocked,这种现象带来的好处就是,首先我们可以集中精力从减少代码的资源消耗上解决问题,带来性能的改善,其次,实在无法优化我们也可以增加机器台数,横向扩展来让性能成倍的提高,这也是用成本换性能的方法。当然,前提是架构上支持负载均衡的分布式架构。
总的来说就是,这种情况要不选择从纵向优化,或者选择从横向扩展,都可以增加。