跳转到主要内容
dustise 提交于 2 December 2014

出处:http://drupalwatchdog.com/volume-3/issue-2/load-testing

作者:Jeff Sheltren

在任何项目中,负载测试都是重要组成部分之一,他让你可以对站点和基础架构在压力下的反应有一个清楚认识。因为这一测试的重要性,所以负载测试应该集成到标准的测试过程中。这一测试的目的是在上线过程或上线后的变更过程中识别出性能瓶颈。

有很多的方法论和工具可以用于性能测试,不过其主要功能一般都包括对站点页面进行大量访问,用足够的流量来触发性能的下降。利用这一过程,识别并解决瓶颈,最终达到提高性能的目的。通过周期性的负载测试,能够更加有效的在早期发现性能问题的征兆,而无需等到大错铸成。

不同的负载测试类型

有多种类型的负载测试配置(有时称为测试计划),他们可以独立运行,也可以协同作业,帮助我们了解站点性能。通常分为以下三种类型:

基线测试

此类测试会用相对较低的流量来运行,目的是获取站点性能的基准信息。这种测试对于跟踪通常情况下的面向用户的性能指标(例如首字节开始时间,完整页面载入时间)是很有用的。基准测试的结果同高流量测试的结果进行比较,或者同普通情况下的运行状况进行比较,就能获知性能是否有异常或恶化的情况。

压力测试

用较高的流量运行,目的在于观察随流量的增加,站点出现性能突降的情况。通过这种测试,可以得知系统在恶化到不可接受之前,能够承受何种数量的访问。另外,这种测试对于发现未知性能瓶颈是非常有效的,这是因为很多系统依赖的服务或者集成的第三方服务都需要较高负载的情况下才会出现问题。一般来说,此类测试是最经常使用的情况。

针对性测试

多数测试是用于覆盖一个站点的所有请求类型和页面类型的。而这种测试是另外一种方式,他的测试目的是集中于一个或几个指定功能的。如果想要增强某个特定页面类型的性能,可以运行这种测试,仅面向指定方面进行测试。

译者按,这种区分方式同我所知的内容不太一样——可能因为我只短暂用过Loadrunner的原因吧。 首先,所有的性能测试方案都是有针对性的,或者针对首页,或者针对登录,或者针对订单列表等等,没有覆盖所有功能的情况。 其次,Loadrunner的两种测试目标,一种是用于测试目标功能的性能上限(例如XX并发的条件下,站点性能开始迅速衰减);另一种是指定性能要求的测试(例如XX并发的条件下,响应时间在XX之内)。

建立一个有效的测试

最难的当然是创建一个真正的测试方案。如果测试方案同实际流量差异很大,那么测试结果反应的性能问题,对于你的实际性能优化工作很难产生实际推动。如果能够用接近实际情况的(对于新站点来说,可能是接近预期情况的)测试方案,能够得到更加可靠的性能测试结果。随着站点通信量的变化,以及功能的增长,负载测试的方案都要随之发生变化。建立和审核一个负载测试计划的要点如下:

  • 浏览分布模式:什么页面浏览比较频繁?用户在不同类型的页面的停留多久?用户最多从什么入口进入站点?

  • 认证用户流量:匿名用户和认证用户的流量占比多少?认证用户和匿名用户浏览的页面有何区别?

  • 内容数量:当建设新站点时,是否有足够多的内容来运行负载测试?如果数量不足,在运行测试之前最好利用Devel模块等自动化手段创建足够多的内容。

何时测试?

有很多方式来对站点进行负载测试。以什么频度测试完全取决于你。有些站点每个月进行一次,有些可能每天进行多次。不管最终决定如何,进行基准测试都是必须的,有了基准测试的结果,才能知道“正常”情况下的性能表现,才能据此来定义服务器端指标和用户端指标的好与坏。

持续集成

当你的开发过程集成了Jenkins这样的工具后,就可以把测试工作集成到这一环境中来。例如在每次准生产环境更新版本时自动进行测试,或者如果你有充足的资源,你可以在每次代码更新的时候都运行一次性能测试。

周期性测试

如果不想每次功能或者代码更新都进行负载测试,一个变通方法就是按照预定的时间表进行测试。可以每天、每周甚至每月进行。越频繁的测试,就越容易把性能问题跟特定的变更关联起来。如果测试之间相距太长时间,就很难鉴别性能问题的源头所在。

手工的针对性测试

在上面两种情况之外,有时需要对某种特定功能进行测试。例如,如果想要举办一个媒体活动,可能会导致很多用户涌入站点,那么对相应的站点着陆页和用户注册等相关页面就需要进行针对性的测试,以确保其负载能力能满足更高要求。

测试结果的解读

性能相关测试的一个困扰就是测试结果中的大量数据,很难在其中区分出重要数据。多数情况下,至少要检验以下几个指标:

  • 第一个字节的时间(Time to first byte ):有些负载测试应用称之为等待时间(Latency)。这个指标通常意味着Drupal的执行时间或者缓存时间。

  • 全页载入时间(Full page load time):也成为响应时间,和上一指标的区别在于,他还关注页面尺寸,网络性能等其他因素。

  • 每秒请求数:在确定流量和基础设施容量时,这一指标非常重要。

  • 错误响应:这是另外一个重要的数据,也是最容易被忽略的数据。有时一个当机的站点能以非常好的成绩通过负载测试,这很明显是无效信息,而且歪曲了真正的性能表现。

按照测试目的的不同,可能还需要关注一下通信量等其他信息。

不管选择什么样的跟踪数据,一旦数据能够在不同的测试结果中进行比较,这些数据的价值将大大提升,能够通过对性能数据趋势的对比,更好的推进优化工作。观察指标的变化是很有价值的,例如指标如何随时间变化,或因为某些代码更新或基础设施变化而产生什么样的后果。

另外一个很值得注意的是,要区分负载测试软件和用户浏览器的不同。例如JMeter不会执行java script,缺省情况下,他也不会载入页面内链接的元素。这些差异一般来说是可以接受的,但有些情况下,你可能还需要借助一些其他工具来做做额外的测试,来获取更接近浏览器行为的测试结果。这些工具一般都无法负担高通信量的负载测试,不过至少他可以用作基线测试。

负载测试中的服务器监控

当你运行负载测试时,你会看到一个结果列表,列表中完全是客户端的性能相关内容,这是因为负载测试软件本来就只能得到这些。然而为了完成对系统瓶颈的定位,在测试运行过程中,对服务器或者服务的监控也是很重要的。当然,这类监控可以让自动系统来做;然而,如果能在测试过程中看到动态演变的数据,也是相当有益的。不同的站点的瓶颈不尽相同,所以最好尽可能多的搜集数据,下面建议初学者关注的内容:

Web Server

观测系统负载(System load),内存使用,交换空间使用,网络流量,磁盘输入输出。同时还要关注Apache的进程数是否已经接近了MaxClients设置,另外别忘了关注Apache的错误日志。

反向代理以及Memcached等缓存系统

关注系统负载,网络吞吐,以及缓存统计。缓存命中率高还是低?为什么是这种命中率?(有可能测试案例只包含了站点页面中很小的一部分,这就会导致缓存命中率畸高)。查看内存使用状况,以及Memcached的evictions情况,就能知道Memcached是否因为内存爆满而提前释放没有过期的缓存内容。

数据库服务器

查看服务器负载以及连接数。查看MySQL的错误日志,看是否有较为罕见的错误发生。确认开启MySQL的慢查询日志,观测这一日志可以对查询进行优化(例如Percona Toolkit中的pt-query-digist)。还可以直接用mysqlreport之类的工具来查看MySQL的统计信息,例如InnoDB缓存使用、锁定等待时间以及查询缓存使用状况等。还可以查看MySQL进程表,来观察是否有频繁出现的查询,或者耗时的查询。

何处测试

有一系列的选项来决定测试的目标环境:开发、准生产以及生产环境,或者其他什么独立的能做负载测试的环境。在理想环境下,负载测试应该针对生产环境进行——这样能够获得最准确的结果。虽然有人通过在凌晨三点或者其他什么相对的闲时进行生产环境的测试,不过也不是每个人都有这种条件。我们的建议是考虑一下性能的需求和目标,然后基于这些条件在近似的环境上做负载测试。

另外一个影响环境选择的要素就是,测试过程中是否新增或删除数据。一般来说,在生产环境上对留言之类的功能进行负载测试很难保证不对真正的用户造成影响。

测试选择的环境越接近生产环境,那么测试的结果就越可信,越可用。大多数情况下,准生产环境是最适合做负载测试的。虽然准生产环境的服务器可能数量和运算能力上都不如生产环境的服务器水平,不过只要他跟生产环境足够相似,那么就仍然可以发现、跟踪性能问题,解决瓶颈问题。

还有一个选择就是在开发环境进行测试。这对有持续集成的环境尤其有用。虽然开发环境跟生产环境可能相去甚远,但是对于发现和解决代码变更产生的性能问题来说,还是相当有帮助的。

当在非生产环境进行测试时,因为环境性能的差异,对所有性能参数都应该打个折扣。即便是这样,对同一环境的持续测试仍然能产生有意义的对比结果。

对于重度使用的系统来说,在上面直接运行性能测试是不可能的。这种情况下,高富帅的选择就是部署一套独立的“负载测试”环境,专门用于这种测试,当然,也可以为接触测试等其他自动化测试共享。重复前文提出的原则:同生产环境越接近,得出的结果就越可靠。对于在云端运行的系统来说,环境可以按需分配,测试完成后释放即可。

有些站点为了获取“真实”数据,会坚持在生产环境进行负载测试。这种情况很难达到,因为独立的准生产环境很难得到需要的数据,一般来说,我们推荐对生产环境只进行低流量的测试,以获取用户方面的性能信息。而重负载的测试,则还是推荐在准生产环境上进行。

Drupal 版本