进行Web应用程序负载测试的步骤 – 案例分析
首先
负载测试非常重要,但是否有可能因为发布时间表优先而被推迟或省略呢?
特别是近年来,由于基于云端运行的前提条件,可能导致事前负载测试被忽视,因为它被认为在发布后进行扩容和横向伸缩更容易。
然而,在某个项目中,我们进行了负载测试,发现它确实很重要,因此以自我警戒的态度,我们将从负载测试的实施开始记录性能调优的流程。
我打算随时添加我参考的链接,以便详细介绍每个工具。
以下数字仅为示例,并进行了适当近似处理。
由于对负载测试的轻视可能会导致的情况
容易想到的事情
-
- サービスの継続に必要なサーバリソースが予算またはサービスの収入を上回った。(ワーストケース)
-
- サービスの継続に必要なサーバリソースが膨大であるため管理がめんどくさい。(まだまし)
-
- もうこれ以上スケールアップ可能なサーバが存在しない。(あるある)
-
- パフォーマンスチューニングしたが、リリース後なのでシステムの刷新にコストがかかる。(あるある)
- サーバ構成に過不足があって無駄なコストを支払っていた。
如果有一个不需要进行负载测试的服务,我认为这些内容很容易想到,因为它已经考虑在内了。
→ 只要有可扩展的架构,大多数通过金钱解决的问题都可以解决。
除了以上列出的实际可能发生的事情外
-
- 構成する各サーバのスケールアップをしてもパフォーマンス改善にほとんど結びつかなかった。
- 構成する各サーバのスケールアウトをしてもパフォーマンス改善にほとんど結びつかなかった。
→ ※实际上,我们已经构建了一个无法扩展的应用程序!
换句话说,负载测试的目的不仅在于测量系统的极限性能,还包括对整个系统进行调优,确保系统具备可扩展的配置。
本章:负载测试案例研究
目标系统结构.
我们将在AWS上构建以下系统,并从Jmeter服务器进行攻击。
-
- ELB
-
- EC2 Webサーバ Apache + PHP
-
- EC2 Jmeter攻撃サーバ ※jmeter-serverを起動
-
- ElastiCache * 2 (Memcached)
- RDS (MySQL)
在这种情况下,使用情况将使用CloudWatch进行监控,为了获取每分钟的详细信息,我们将启用详细监控功能(额外收费)。
在开始施加负载之前,先合理地设计一个场景试一试。
请设置一个几乎静态的文件,并查看其吞吐量和各个服务器的资源使用情况。
例如,可以设置一个名为uniqid.php的文件,其中只包含uniqid();的返回值,并通过调用它来检查。
JMeter选项
实际执行结果示例
资源使用情况示例
台数CPU使用率Jmeterc3.xlarge11%Webc3.xlarge110%RDSm3.large10%ElastiCachet1.micro10%
这个结果该如何解读?
尽管所有服务器的资源都有空闲,但吞吐量(164req/sec)明显很差,因此当前状态下无法施加正常负载。
我们将提出可能的假设,并逐个排除来进行进一步研究。
关于应用程序可能存在问题的可能性
由于这次考试是最简单的模式,所以我将跳过这一项。
关于基础设施可能存在问题的可能性
只要JMeter攻击服务器的负载很低,为了排除网络问题,将JMeter攻击服务器构建为Web服务器,并对本地主机进行攻击。
→ 结果几乎没有改善。
有可能是Apache的配置存在问题。
→ 我嘗試過更改同時連接數,但改善幾乎不明顯。
关于考试情景可能存在问题的可能性
在最初的方案中,我们在“通过树形结构展示结果”选项里只对错误进行了检查并使用。但是通过禁用此功能,整体吞吐量得到了改善。
由于没有显示错误时的检查结果,我们原本认为这不会对负载造成影响。但是根据从新加坡区域构建的服务器传输至日本的Jmeter客户端的负载情况来看,这个功能实际上是拖了我们的后腿。
例子的执行结果
资源使用情况示例
台数CPU使用率Web兼Jmeter攻撃c3.xlarge198%RDSm3.large10%ElastiCachet2.small20%
你如何解读这个结果?
由于Web服务器存在CPU瓶颈,所以该系统的极限值无法超过每台Web服务器1200req/sec。
建立应用程序的性能评估将取决于能否接近这个数值。
重新为原始系统准备Jmter的脚本。
执行结果示例
资源使用情况示例
台数CPU使用率Web兼Jmeter攻撃c3.xlarge120%RDSm3.large110%ElastiCachet2.small235%
这个结果该如何解读?
-
- どのリソースのCPUもボトルネックになっていないのに全体的なスループットが低すぎる。
-
- 特徴的なのは、midiumの応答時間は速いのに、90%lineとMaxが非常に悪い。(memcached接続またはDB接続等の外部リソースの接続待ちの可能性が高い。)
-
- ここには記載していないが、CPU負荷以外も特にボトルネックが見当たらなかった。
- 最適なアプリケーションであれば、Jmeterで負荷をかけ続けているのでどこかにリソースの逼迫が見えるはず。
这样下去,Web服务器和RDS的扩展和扩容可能都变得毫无意义。
→为了测试,我们改变了实例类型进行了测试,但吞吐量几乎没有变化。
由于网络配置问题和Jmeter场景问题已经解决,因此剩下的可能是应用程序问题,决定引入性能分析工具进行调查。
引入xhprof。
使用PHP的性能分析工具「XHProf」的方法等,通过各种谷歌搜索适当地进行安装。为了可视化,我还安装了graphviz,但是在使用yum安装后发生了分段错误,于是奇怪地通过yum安装32位版本后,正常运行了。
发现PDO::connect()和Memcached::connect()有时候会非常耗时。
MySQL连接的持久性
将数据库连接改为使用pconnect,仅此一项就将吞吐量从129req/sec提升至170req/sec左右。即使查看资源,同时连接数已经附着到请求数上,而新连接数却急剧减少。
Memcached连接的持久化
在比较PECL::Memcache和PECL::Memcached之后,由于PECL::Memcached更受好评,我选择使用了PECL::Memcached。然而,在一篇文章中发现,PECL::Memcached的持久性可以通过指定Memcached::connect(“连接字符串”)来实现。尽管我尝试了这种方法,但实际效果几乎没有改变。更糟糕的是,在我的环境下出现了分段错误,所以我决定放弃使用PECL::Memcached。
我尝试安装PECL::memcache后,吞吐量显著改善。从每秒170个请求到接近500个请求。
查看资源时,与其同时建立连接的数量替代了请求的数量,而新建连接的数量大幅减少。
这种情况下资源的使用情况的例子
台数CPU使用率Web兼Jmeter攻撃c3.xlarge180%RDSm3.large135%ElastiCachet2.small28%
尽管吞吐量有所提高,但由于新连接数急剧减少,导致RDS和ElastiCache的负载降低。
考虑到这个状态下可能存在Web服务器的CPU瓶颈,我们可以尝试增加Web服务器兼攻击服务器。
台数CPU使用率Web兼Jmeter攻撃c3.xlarge280%RDSm3.large190%ElastiCachet2.small212%
虽然负载转移到了RDS上,但吞吐量却达到了两倍的每秒1000个请求。
通过增加Web服务器,整体吞吐量线性地得到了提升。
要进一步提高吞吐量,似乎可以通过升级RDS服务器来实现。
最终的感受
-
- jmeter-server(攻撃サーバを複数立てる方式)を初めて試してみたが、いい感じ。(ここでは書きませんでしたが、jmeter-clientとバージョンを合わせる必要があったり、portを開けたりする必要はあります。)
-
- 上記jmeter-serverの利用に関してはクラスメソッドさんのSpotInstanceとJMeterを使って400万req/minの負荷試験を行うの記事が熱いです。参考にさせて頂きました。
-
- 負荷試験をやらなかったら、Webサーバ一台あたりで本来の能力の数分の1しかこなせなかったということで、冷やっとしました。
-
- xhprof + graphbizでのプロファイリングはなんか眺めているだけで楽しい。
- 高負荷時には永続的接続は超重要
广告
本文的内容是因为这篇文章,经过曲折经历,最终出版了一本关于负载测试的专业知识的书籍。虽然价格略高,但是这本书主要介绍了云端设计、负载测试和负载防护方面的入门知识,对于对此感兴趣的人来说,请务必阅读一下。