首页 > 代码库 > 柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法、指标、工具、定位)

柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法、指标、工具、定位)

                                    柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法、指标、工具、定位)

柯南君的朋友“闲哥”最近遇到了点困扰---”大型网站平台如何对待性能优化,以及如何针对性调优?“,柯南君今天,想谈一下性能优化的战略,主要是一些企业架构级别的技术和方法。柯南君将自己的个人经验和各家公司大咖的经验一起汇总给大家,如有瑕疵,请大家及时指正。

柯南君有句自律的口头语“如果你不能成为一个追求性能的疯子,那么性能将会把你变成疯子

       序曲:

如何评估平台系统需求与性能指标?在这里,柯南君在这里小谈一下(因为每一家公司都不一样,所以,仅仅是举个例子)我先和大家探讨一下“性能测试方法

1.V模型的标准测试策略



备注:
       性能测试是V模型中验证整体系统的重要步骤

2.常见的性能测试方法

 1)负载测试
  在这里,负载测试是指最常见的性能测试,用户最常见的性能需求是“既要马儿跑,又要马儿少吃草”。因此负载测试主要是考察软件在系统既定负载下的性能表现,柯南君这么理解的:
   ① 负载测试是站在用户的角度去观察在一定条件下软件系统的表现;
   ② 负载测试的预期结果是用户的性能需求得到满足。此指标一般体现为相应时间、交易容量、并发容量、资源使用率等(下章 主要讲解性能需求指标
 2)压力测试
  压力测试是为了考察系统在极端条件下的表现,极端条件可以是超负荷的交易量和并发用户数。注意,这个极端条件并不一定是用户性能需求的,可能要远远高于用户的性能需求。可以这样理解,压力测试和负载测试不同的是压力测试的结果是系统出现问题,而我们要考察的是系统处理问题的方式。比如说,我们期待一个系统在面临压力的情况下能够保持稳定,处理速度可以变慢,但不能系统崩溃。因此,压力测试是能让我们识别系统的弱点和在极限负载下程序将如何运行。 
 3)并发测试
  我们在做压力测试的时候,往往要增加比负载测试更多的并发用户和交易量,这是为什么?验证系统的并发处理能力。一般是和服务器端建立大量的并发连接,通过客户端的响应时间和服务器端的性能监测情况来判断系统是否达到了既定的并发能力指标。负载测试往往就会使用并发来创造负载,之所以把并发测试单独提出来,是因为并发测试往往涉及服务器的并发容量,以及多进程/多线程协调同步可能带来的问题。这是要特别注意,必须测试的。
 4)基准测试
  当软件系统中增加一个新的模块的时候,需要做基准测试,以判断新模块对整个软件系统的性能影响。按照基准测试的方法,需要打开/关闭新模块至少各做一次测试。关闭模块之前的系统各个性能指标记下来作为基准(Benchmark),然后与打开模块状态下的系统性能指标作比较,以判断模块对系统性能的影响。
 5)稳定性测试
   “路遥知马力”,在这里我们要说的是和性能测试有关的稳定性测试,即测试系统在一定负载下运行长时间后是否会发生问题。软件系统的有些问题是不能一下子就暴露出来的,或者说是需要时间积累才能达到能够度量的程度。为什么会需要这样的测试呢?因为有些软件的问题只有在运行一天或一个星期甚至更长的时间才会暴露。这种问题一般是程序占用资源却不能及时释放而引起的。比如,内存泄漏问题就是经过一段时间积累才会慢慢变得显著,在运行初期却很难检测出来;还有客户端和服务器在负载运行一段时间后,建立了大量的连接通路,却不能有效地复用或及时释放。
 6)可恢复测试
  测试系统能否快速地从错误状态中恢复到正常状态。比如,在一个配有负载均衡的系统中,主机承受了压力无法正常工作后,备份机是否能够快速地接管负载。可恢复测试通常结合压力测试一起来做。
        提示:每种测试有其存在的空间和目的。当我们接手一个软件项目后,在有限的资源条件下,选择去做哪一种测试,这应该根据当前软件过程阶段和项目的本身特点来做选择。比如,在集成测试的时候要做基准测试,在软件产品每个发布点要做性能测试。

          一、估算网站系统性能需求与性能需求指标

(一)时间特性的需求

1.普遍情况下,根据国际标准3 - 5 - 8原则,推算业务处理时间;
2.登录时间不超过5秒;
3.检索票务时间不超过5秒;
4.页面之间跳转时间不超过3秒;
5.平均时间在3~5秒以内;

(二)系统容量需求(用例为模拟)

1.在线用户数,范围值:10000;
2.注册会员数,范围值:500万;
3.SKU 范围值: 80万;

(三)一般网站的建设需求:(用例为模拟)

1.网站系统在2000个用户的负载下,所有业务动作是否可用及稳定;
2.网站系统在2000个用户的负载下,连续运行72个小时过程中,用户登录、下单、支付等业务动作是否可用并稳定;
3.网站系统在2000个用户在线(10000 * 20%),即2000个并发用户操作负载下,连续工作72个小时过程中,以上业务动作是否可用及稳定。(80/20原则,即80%的压力是由20%用户产生的);
4.网站系统在80G的业务数据、2000个并发用户在线(10000*20%),即2000个并发用户运行的负载下,连续运行72个小时过程中,以上任务是否可用及稳定;

(四)性能需求指标:(用例为模拟)

根据既有的性能需求对本系统的用户访问量、系统处理能力、业务处理能力、系统响应时间、 

容灾需求性能指标、

 

网络流量等5个主要方面进行分析估算。其中部分指标也参考测试行业标准,得出该项目具体性能指标。

1.并发用户指标 
1)2000 >= 并发用户数 >= 1500(估算并结合系统需求得出 2/8理论推出)
2)系统有效工作时间要求≥99.5%(用行业标准得出)
3)Web服务持续稳定工作时间≥3天(72小时)(用行业标准得出)
2.系统稳定性指标 
1)系统有效工作时间要求≥99.5%(用行业标准得出)
2)Web服务持续稳定工作时间≥3天(72小时)(用行业标准得出)
3.系统吞吐量指标(多层体系结构)
1)完成业务情况(数据库容量)≥1000万(笔)交易(性能需求)
4.业务处理能力性能指标
1)在业务高峰时,每分钟能够同时处理1500笔数据维护更新操作;1000笔的数据查询操作。(估算得出)
2)在2000个并发用户访问时,确定条件的信息查询响应时间小于8秒钟。(用行业标准得出)
3)每笔业务的响应时间在5秒以内。(用行业标准得出)
4)登录要求响应时间在5秒以内。(用行业标准得出)
5)业务处理(每秒请求数)≥4次/秒(估算得出)
6)TPS(每秒交易数)≥1500(估算得出)
5.容灾需求性能指标(多层体系结构)
1)并发用户数≥2400(估算得出)
2)每天完成业务情况≥700万(笔)交易(用行业标准得出)
3)每分钟完成的业务≥5000(笔)交易(估算得出)
6.网络流量分析估算

      二、系统性能定义

    让我们先来说说如何什么是系统性能。这个定义非常关键,如果我们不清楚什么是系统性能,那么我们将无法定位之。
  • Throughput ,吞吐量。也就是每秒钟可以处理的请求数,任务数。
  • Latency, 系统延迟。也就是系统在处理一个请求或一个任务时的延迟。
一般来说,一个系统的性能受到这两个条件的约束,缺一不可。比如,我的系统可以顶得住一百万的并发,但是系统的延迟是2分钟以上,那么,这个一百万的负载毫无意义。系统延迟很短,但是吞吐量很低,同样没有意义。所以,一个好的系统的性能测试必然受到这两个条件的同时作用。 有经验的朋友一定知道,这两个东西的一些关系:
  • Throughput越大,Latency会越差。因为请求量过大,系统太繁忙,所以响应速度自然会低。
  • Latency越好,能支持的Throughput就会越高。因为Latency短说明处理速度快,于是就可以处理更多的请求。

          三、系统性能测试

经过上述的说明,我们知道要测试系统的性能,需要我们收集系统的 Throughput Latency 这两个值。
  • 首先,需要定义 Latency 这个值,比如说,对于网站系统响应时间必需是 5 秒以内(对于某些实时系统可能需要定义的更短,比如 5ms 以内 见”

    估算网站系统性能需求与性能需求指标

    “,这个更根据不同的业务来定义)
  • 其次,开发性能测试工具,一个工具用来制造高强度的 Throughput,另一个工具用来测量 Latency。对于第一个工具,你可以参考一下“十个免费的 Web 压力测试工具”(见备注),关于如何测量 Latency,你可以在代码中测量,但是这样会影响程序的执行,而且只能测试到程序内部的 Latency,真正的 Latency 是整个系统都算上,包括操作系统和网络的延时,你可以使用 Wireshark 来抓网络包来测量。这两个工具具体怎么做,这个还请大家自己思考去了。
备注:
	   1)Grinder
	      Grinder是一个开源的JVM负载测试框架,它通过很多负载注射器来为分布式测试提供了便利。 支持用于执行测试脚本的Jython脚本引擎HTTP测试可通过HTTP代理进行管理。根据项目网站的说法,Grinder的 主要目标用户是“理解他们所测代码的人——Grinder不仅仅是带有一组相关响应时间的‘黑盒’测试。由于测试过程可以进行编码——而不是简单地脚本 化,所以程序员能测试应用中内部的各个层次,而不仅仅是通过用户界面测试响应时间。
             
	   Pylot是一款开源的测试web service性能和扩展性的工具,它运行HTTP 负载测试,这对容量计划,确定基准点,分析以及系统调优都很有用处。Pylot产生并发负载(HTTP Requests),检验服务器响应,以及产生带有metrics的报表。通过GUI或者shell/console来执行和监视test suites。               
              
     
           2)Pylot
 	3)Web Capacity Analysis Tool (WCAT) 
	    这是一种轻量级负载生成实用工具,不仅能够重现对 Web 服务器(或负载平衡服务器场)的脚本 HTTP 请求,同时还可以收集性能统计数据供日后分析之用。WCAT 是多线程应用程序,并且支持从单个源控制多个负载测试客户端,因此您可以模拟数千个并发用户。该实用工具利用您的旧机器作为测试客户端,其中每个测试客户端又可以产生多个虚拟客户端(最大数量取决于客户端机器的网络适配器和其他硬件)。您可以选择使用 HTTP 1.0 还是 HTTP 1.1 请求,以及是否使用 SSL。并且,如果测试方案需要,您还可以使用脚本执行的基本或 NTLM 身份验证来访问站点的受限部分。(如果您的站点使用 cookie、表单或基于会话的身份验证,那您可以创建正确的 GET 或 POST 请求来对测试用户进行身份验证。)WCAT 还可管理您站点可能设置的任何 cookie,所以配置文件和会话信息将永久保存。 
	4)fwptt 
	   fwptt 也是一个用来进行WEB应用负载测试的工具。它可以记录一般的请求,也可以记录Ajax请求。它可以用来测试 asp.net, jsp, php 或是其它的Web应用。 	
        5)JCrawler
	   JCrawler是一个开源( CPL) 的WEB应用压力测试工具。通过其名字,你就可以知道这是一个用Java写的像网页爬虫一样的工具。只要你给其几个URL,它就可以开始爬过去了,它用一种特殊的方式来产生你WEB应用的负载。这个工具可以用来测试搜索引擎对你站点产生的负载。当然,其还有另一功能,你可以建立你的网站地图和再点击一下,将自动提交Sitemap给前5名的搜索引擎!
        6) Apache JMeter
	   Apache JMeter是一个专门为运行和服务器装载测试而设计的、100%的纯Java桌面运行程序。原先它是为Web/HTTP测试而设计的,但是它已经扩展以支持各种各样的测试模块。它和用于HTTP和SQL数据库(使用JDBC)的模块一起运送。它可以用来测试静止资料库或者活动资料库中的服务器的运行情况,可以用来模拟对服务器或者网络系统加以重负荷以测试它的抵抗力,或者用来分析不同负荷类型下的所有运行情况。它也提供了一个可替换的界面用来定制数据显示,测试同步及测试的创建和执行。
        7) Siege
	   Siege(英文意思是围攻)是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。 Siege 支持基本的认证,cookies, HTTP 和 HTTPS 协议。
       8) http_load 
	   http_load 以并行复用的方式运行,用以测试web服务器的吞吐量与负载。但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会把客户机搞死。可以可以测试HTTPS类的网站请求
      9) Web Polygraph
	   Web Polygraph这个软件也是一个用于测试WEB性能的工具,这个工具是很多公司的标准测试工具,包括微软在分析其软件性能的时候,也是使用这个工具做为基准工具的。很多招聘测试员的广告中都注明需要熟练掌握这个测试工具。
     10) OpenSTA
	   OpenSTA是一个免费的、开放源代码的web性能测试工具,能录制功能非常强大的脚本过程,执行性能测试。例如虚拟多个不同的用户同时登陆被测试网站。其还能对录制的测试脚本进行,按指定的语法进行编辑。在录制完测试脚本后,可以对测试脚本进行编辑,以便进行特定的性能指标分析。其较为丰富的图形化测试结果大大提高了测试报告的可阅读性。OpenSTA 基于CORBA 的结构体系,它通过虚拟一个proxy,使用其专用的脚本控制语言,记录通过proxy 的一切HTTP/S traffic。通过分析OpenSTA的性能指标收集器收集的各项性能指标,以及HTTP 数据,对系统的性能进行分析。
  • 最后,开始性能测试。你需要不断地提升测试的 Throughput,然后观察系统的负载情况,如果系统顶得住,那就观察 Latency 的值。这样,你就可以找到系统的最大负载,并且你可以知道系统的响应延时是多少。
  再多说一些,
  • 关于 Latency,如果吞吐量很少,这个值估计会非常稳定,当吞吐量越来越大时,系统的 Latency 会出现非常剧烈的抖动,所以,我们在测量 Latency 的时候,我们需要注意到 Latency 的分布,也就是说,有百分之几的在我们允许的范围,有百分之几的超出了,有百分之几的完全不可接受。也许,平均下来的 Latency 达标了,但是其中仅有 50% 的达到了我们可接受的范围。那也没有意义。
  • 关于性能测试,我们还需要定义一个时间段。比如:在某个吞吐量上持续 15 分钟。因为当负载到达的时候,系统会变得不稳定,当过了一两分钟后,系统才会稳定。另外,也有可能是,你的系统在这个负载下前几分钟还表现正常,然后就不稳定了,甚至垮了。所以,需要这么一段时间。这个值,我们叫做峰值极限。
  • 性能测试还需要做 Soak Test,也就是在某个吞吐量下,系统可以持续跑一周甚至更长。这个值,我们叫做系统的正常运行的负载极限
  性能测试有很多很复要的东西,比如:burst test 等。 这里不能一一详述,这里只说了一些和性能调优相关的东西。总之,性能测试是一细活和累活。

  四、定位性能瓶颈

          有了上面的铺垫,我们就可以测试到到系统的性能了,再调优之前,我们先来说说如何找到性能的瓶颈。我见过很多朋友会觉得这很容易,但是仔细一问,其实他们并没有一个比较系统的方法。

(一)查看操作系统负载

    首先,当我们系统有问题的时候,我们不要急于去调查我们代码,这个毫无意义。我们首要需要看的是操作系统的报告。看看操作系统的 CPU 利用率,看看内存使用率,看看操作系统的 IO,还有网络的 IO,网络链接数,等等。Windows 下的 perfmon 是一个很不错的工具,Linux 下也有很多相关的命令和工具,比如:SystemTap,LatencyTOP,vmstat, sar, iostat, top, tcpdump 等等 。通过观察这些数据,我们就可以知道我们的软件的性能基本上出在哪里。比如:
 1.先看 CPU 利用率,如果 CPU 利用率不高,但是系统的 Throughput 和 Latency 上不去了,这说明我们的程序并没有忙于计算,而是忙于别的一些事,比如 IO。(另外,CPU 的利用率还要看内核态的和用户态的,内核态的一上去了,整个系统的性能就下来了。而对于多核 CPU 来说,CPU 0 是相当关键的,如果 CPU 0 的负载高,那么会影响其它核的性能,因为 CPU 各核间是需要有调度的,这靠 CPU0 完成)
 2.然后,我们可以看一下 IO 大不大,IO 和 CPU 一般是反着来的,CPU 利用率高则 IO 不大,IO 大则 CPU 就小。关于 IO,我们要看三个事,一个是磁盘文件 IO,一个是驱动程序的 IO(如:网卡),一个是内存换页率。这三个事都会影响系统性能。
 3.然后,查看一下网络带宽使用情况,在 Linux 下,你可以使用 iftop, iptraf, ntop, tcpdump 这些命令来查看。或是用 Wireshark 来查看。
 4.如果 CPU 不高,IO 不高,内存使用不高,网络带宽使用不高。但是系统的性能上不去。这说明你的程序有问题,比如,你的程序被阻塞了。可能是因为等那个锁,可能是因为等某个资源,或者是在切换上下文。
  通过了解操作系统的性能,我们才知道性能的问题,比如:带宽不够,内存不够,TCP 缓冲区不够,等等,很多时候,不需要调整程序的,只需要调整一下硬件或操作系统的配置就可以了

(二)使用 Profiler 测试

    接下来,我们需要使用性能检测工具,也就是使用某个 Profiler 来差看一下我们程序的运行性能。如:Java 的 JProfiler/TPTP/CodePro Profiler,GNU 的 gprof,IBM 的 PurifyPlus,Intel 的 VTune,AMD 的 CodeAnalyst,还有 Linux 下的 OProfile/perf,后面两个可以让你对你的代码优化到 CPU 的微指令级别,如果你关心 CPU 的 L1/L2的缓存调优,那么你需要考虑一下使用 VTune。 使用这些 Profiler 工具,可以让你程序中各个模块函数甚至指令的很多东西,如:运行的时间 ,调用的次数CPU 的利用率,等等。这些东西对我们来说非常有用。
我们重点观察运行时间最多,调用次数最多的那些函数和指令。这里注意一下,对于调用次数多但是时间很短的函数,你可能只需要轻微优化一下,你的性能就上去了(比如:某函数一秒种被调用 100 万次,你想想如果你让这个函数提高0.01毫秒的时间 ,这会给你带来多大的性能)
使用 Profiler 有个问题我们需要注意一下,因为 Profiler 会让你的程序运行的性能变低,像 PurifyPlus 这样的工具会在你的代码中插入很多代码,会导致你的程序运行效率变低,从而没发测试出在高吞吐量下的系统的性能,对此,一般有两个方法来定位系统瓶颈:
 1.在你的代码中自己做统计,使用微秒级的计时器和函数调用计算器,每隔 10 秒把统计 log 到文件中。
  2.分段注释你的代码块,让一些函数空转,做 Hard Code 的 Mock,然后再测试一下系统的 Throughput 和 Latency 是否有质的变化,如果有,那么被注释的函数就是性能瓶颈,再在这个函数体内注释代码,直到找到最耗性能的语句。
最后再说一点,对于性能测试,不同的 Throughput 会出现不同的测试结果,不同的测试数据也会有不同的测试结果。所以,用于性能测试的数据非常重要,性能测试中,我们需要观测试不同 Throughput 的结果


待续....



柯南君:教你如何对待大型电商平台的性能优化?之 一 (方法、指标、工具、定位)