最近一直纠结性能分析与调优如何下手,先从硬件开始,仍是先从代码或数据库。从操做系统(CPU调度,内存管理,进程调度,磁盘I/O)、网络、协议(HTTP, TCP/IP ),仍是从应用程序代码,数据库调优,中间件配置等方面入手。php
单一个中间件又分web中间件(apache 、IIS),应用中间件(tomcat 、weblogic 、webSphere )等,虽然都是中间件,每同样拎出来往深了学都不是一朝一夕之功。但调优对于每一项的要求又不只仅是“知道”或“会使用”这么简单。起码要达到“如何更好的使用”。html
常看到性能测试书中说,性能测试不仅仅是性能测试工程师一我的的事儿。须要DBA 、开发人员、运维人员的配合完成。可是在很多状况下性能测试是由性能测试人员独立完成的,退一步就算由其它人员的协助,了解系统架构的的各个模块对于自身的提升也有很大帮助,同进也更能获得别人的尊重。前端
再说性能调优以前,咱们有必要再提一下进行测试的目的,或者咱们进行性能测试的初衷是什么?web
能力验证:验证某系统在必定条件具备什么样的能力。面试
能力规划:如何使系统达到咱们要求的性能能力。算法
应用程序诊断:好比内存泄漏,经过功能测试很难发现,但经过性能测试却很容易发现。数据库
性能调优:知足用户需求,进一步进行系统分析找出瓶颈,优化瓶颈,提升系统总体性能。apache
通常系统的瓶颈 windows
性能测试调优须要先发现瓶颈,那么系统通常会存在哪些瓶颈:后端
硬件上的性能瓶颈:
通常指的是CPU、内存、磁盘I/O 方面的问题,分为服务器硬件瓶颈、网络瓶颈(对局域网能够不考虑)、服务器操做系统瓶颈(参数配置)、中间件瓶颈(参数配置、数据库、web服务器等)、应用瓶颈(SQL 语句、数据库设计、业务逻辑、算法等)。
应用软件上的性能瓶颈:
通常指的是应用服务器、web 服务器等应用软件,还包括数据库系统。
例如:中间件weblogic 平台上配置的JDBC链接池的参数设置不合理,形成的瓶颈。
应用程序上的性能瓶颈:
通常指的是开发人员新开发出来的应用程序。
例如,程序架构规划不合理,程序自己设计有问题(串行处理、请求的处理线程不够),形成系统在大量用户方位时性能低下而形成的瓶颈。
操做系统上的性能瓶颈:
通常指的是windows、UNIX、Linux等操做系统。
例如,在进行性能测试,出现物理内存不足时,虚拟内存设置也不合理,虚拟内存的交换效率就会大大下降,从而致使行为的响应时间大大增长,这时认为操做系统上出现性能瓶颈。
网络设备上的性能瓶颈:
通常指的是防火墙、动态负载均衡器、交换机等设备。
例如,在动态负载均衡器上设置了动态分发负载的机制,当发现某个应用服务器上的硬件资源已经到达极限时,动态负载均衡器将后续的交易请求发送到其余负载较轻的应用服务器上。在测试时发现,动态负载均衡器没有起到相应的做用,这时能够认为网络瓶颈。
性能测试出现的缘由及其定位十分复杂,这里只是简单介绍常见的几种瓶颈类型和特征,而性能测试所须要作的就是根据各类状况因素综合考虑,而后协助开发人员\DBA\运维人员一块儿定位性能瓶颈。
通常性能调优步骤
通常性能问题调优的步骤:
步骤一:肯定问题
应用程序代码:在一般状况下,不少程序的性能问题都是写出来的,所以对于发现瓶颈的模块,应该首先检查一下代码。
数据库配置:常常引发整个系统运行缓慢,一些诸如oracle 的大型数据库都是须要DBA进行正确的参数调整才能投产的。
操做系统配置:不合理就可能引发系统瓶颈。
硬件设置:硬盘速度、内存大小等都是容易引发瓶颈的缘由,所以这些都是分析的重点。
网络:网络负载太重致使网络冲突和网络延迟。
步骤二:肯定问题
当肯定了问题以后,咱们要明确这个问题影响的是响应时间吞吐量,仍是其余问题?是多数用户仍是少数用户遇到了问题?若是是少数用户,这几个用户与其它用户的操做有什么不用?系统资源监控的结果是否正常?CPU的使用是否到达极限?I/O 状况如何?问题是否集中在某一类模块中? 是客户端仍是服务器出现问题? 系统硬件配置是否够用?实际负载是否超过了系统的负载能力? 是否未对系统进行优化?
经过这些分析及一些与系统相关的问题,能够对系统瓶颈有更深刻的了解,进而分析出真正的缘由。
步骤三: 肯定调整目标和解决方案
得高系统吞吐理,缩短响应时间,更好地支持并发。
步骤四:测试解决方案
对经过解决方案调优后的系统进行基准测试。(基准测试是指经过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试)
步骤五:分析调优结果
系统调优是否达到或者超出了预约目标?系统是总体性能获得了改善,仍是以系统某部分性能来解决其余问题。调优是否能够结束了。
最后,若是达到了预期目标,调优工做就基本能够结束了。
下面算是一个技巧,如面试官问到一个性能问题假设,我不知道性能问题出在哪儿时,能够按照这个思路回答^_^
• 查找瓶颈时按如下顺序,由易到难。
服务器硬件瓶颈---〉网络瓶颈(对局域网,能够不考虑)---〉服务器操做系统瓶颈(参数配置)---〉中间件瓶颈(参数配置,数据库,web服务器等)---〉应用瓶颈(SQL语句、数据库设计、业务逻辑、算法等)
注:以上过程并非每一个分析中都须要的,要根据测试目的和要求来肯定分析的深度。对一些要求低的,咱们分析到应用系统在未来大的负载压力(并发用户数、数据量)下,系统的硬件瓶颈在哪儿就够了。
• 分段排除法 颇有效
性能测试调优应该注意的要点:
要点1: 在应用系统的设计开发过程当中,应始终把性能放在考虑的范围内。
要点2: 肯定清晰明确的性能目标是关键。
要点3: 必须保证调优后的程序运行正确。
要点4: 系统的性能更大程度上取决于良好的设计,调优技巧只是一个辅助手段。
要点5: 调优过程是迭代渐进的过程,每一次调优的结果都要反馈到后续的代码开发中去。
要点6: 性能调优不能以牺牲代码的可读性和可维护性为代码。
本文只介绍了一些性能调优的要关注的东西以及性能调优的通常要点。并无具体说如何对系统的每一个部件进行调优,如何要细说也不是一两书能说清的,对知识面的要求也很是高,是我目前的能力没法触摸的。
这里作个总结:
《性能测试知多少》系列基本完结,虽然时间拉得比较长,但我没有把它给太监。虽然内容都在空谈性能测试理论知识,但我认为这些东西对于你从事性能测试工做必不可少。固然,我在“ jmeter基础 ” 与“ loadrunner 技巧 ” 中讲解两个性能测试工具的使用。
若是个人这些文章对于想了解和学习性能的同窗带来一丝的帮助,我将很是开心。我不是高手,只是和你一块儿热爱测试技术的初学者,只是比较喜欢总结;也时常为前途迷茫,但我知道只要断去学习,路就在前方。我后面会整理性能调优的相关文章。
动态的 Web 应用程序可以存储大量信息,让用户可以经过熟悉的界面当即访问这些信息。可是,随着应用程序愈来愈受欢迎,可能会发现对请求的响应速度没有之前那么快了。 开发人员应该了解 Web 应用程序处理 Web 请求的方式,知道在 Web 应用程序开发中能够作什么,不能作什么,这有助于减小往后的麻烦。
静态的 Web 请求(好比图 1 所示的请求)很容易理解。客户机链接服务器(一般经过 TCP 端口 80),使用 HTTP 协议发出一个简单的请求。
服务器解析这个请求,把它映射到文件系统上的一个文件。而后,服务器向客户机发送一些描述有效负载(好比网页或图像)的响应头,最后向客户机发送文件。
在 上面的场景中可能出现几个瓶颈。若是请求的变化很大,致使没法有效地使用操做系统的磁盘缓存,那么服务器的磁盘会很忙,到了某种程度以后,就会减慢整个过 程。若是为客户机提供数据的网络通道饱和了,就会影响全部客户机。可是,除了这些情况以外,“接收请求,发送文件” 过程仍是至关高效的。
通 过作一些假设,能够大体体会静态服务器的性能。假设一个请求的服务时间是 10ms(主要受到磁头寻道时间的限制),那么大约每秒 100 个请求就会使磁盘接近饱和(10msec/request / 1 second = 100 requests/second)。若是要发送 10K 的文档,就会产生大约 8mbit/sec 的 Web 通讯流(100 requests/second * 10 KBytes/request * 8bits/byte)。若是能够从内存缓存中获取文件,就能够下降平均服务时间,所以增长服务器每秒可以处理的链接数。若是您有磁盘服务时间或平均请求 延时的真实数据,能够把它们放进上面的算式,从而计算出更准确的性能估计值。
既然服务器的处理容量是平均请求服务时间的倒数,那么若是服务时间加倍,服务器的处理容量(每秒处理的链接数)就会减半。请记住这一点,下面看看动态应用程序的状况。
动态应用程序的流程依赖于应用程序的具体状况,可是通常状况下与图 2 类似。
与前一个示例中的客户机同样,图 2 中的客户机首先发出一个请求。静态请求和动态请求之间实际上没什么差别(有时候 .php 或 .cgi 等扩展名可能意味着动态请求,可是它们可能引发误解)。如何处理请求是由 Web 服务器决定的。
在 图 2 中,请求被发送到一个应用服务器,好比运行一个 Java™ 应用程序的 Solaris 系统。应用服务器执行一些处理,而后向数据库查询更多的信息。获得这些信息以后,应用服务器生成一个 HTML 页面,这个页面由 Web 服务器转发给客户机。所以,这个请求的服务时间是几个部分的总和。若是数据库访问花费 7ms,应用服务器花费 13ms,Web 服务器花费 5ms,那么网页的服务时间就是 25ms。根据前面介绍的倒数规则,各个组件的容量分别是每秒 14二、77 和 200 个请求。所以,瓶颈是应用服务器,它使这个系统每秒只能处理 77 个链接;超过这个数量以后,Web 服务器被迫等待,链接开始排队。
但 是,必定要注意一点:由于系统每秒只能分派 77 个链接,而一个链接须要的处理时间是 25ms,因此并不是每一个应用程序用户的请求都可以在 25ms 内获得处理。每一个组件每次只能处理一个链接,因此在高峰负载下,请求不得不等待 CPU 时间。在上面的示例中,考虑到排队时间和 25ms 的处理时间,平均请求服务时间最终会超过 1.1 秒。关于解决这些排队问题的更多信息,请参见 参考资料。
经过这些示例能够得出如下结论:
在用户发出请求和得到最终页面之间的步骤越多,整个过程就越慢,系统容量就越低。
随着页面请求速率的增长,这种效应会愈来愈显著。
在项目开始时作出的体系结构决策也会影响站点处理负载的能力。
本文的其他部分将深刻讨论这些问题。
应用程序(包括 Web 应用程序)的体系结构经常按照层来描述。静态站点能够被看做只有一层 —— Web 服务器。若是用 Web 服务器运行某种脚本语言(好比 PHP),从而链接数据库,那么这能够看做两层。前一节中的示例有三层,即前端 Web 服务器、应用服务器和数据库。
一 个软件也可能由多层组成,这取决于您谈话的对象。例如,PHP 脚本可能使用一个模板引擎把业务逻辑与表示分隔开,它能够被看做单独的两层。Java 应用程序可能经过 Java servlet 执行表示任务,servlet 经过与 Enterprise Java Bean (EJB) 通讯执行业务逻辑,EJB 经过链接数据库获取更多信息。所以,换一个角度来看,三层体系结构多是另外一副样子,尤为是在涉及不一样的工具集时。
尽管应用程序的体系结构各不相同,可是有一些常见的体系结构趋势。在通常状况下,应用程序须要四个功能层:
客户机层
表示层
业务逻辑层
数据层
在 Web 应用程序中,客户机层由 Web 浏览器处理。浏览器显示 HTML 并执行 Javascript(以及 Java applet、ActiveX 或 Flash applet),从而向用户显示信息和收集用户信息。表示层是从服务器到客户机的接口,它负责控制输出的格式,让输出能够在客户机上显示。业务逻辑层实施 业务规则(好比计算和工做流),从而驱动应用程序。最后,数据访问层是持久化的数据存储,好比数据库或文件存储。
大多数应用程序须要全部这四层的功能,尽管它们可能不须要明显完整地实现这些层。
另外一种流行的体系结构是 Model-View-Controller,这是一种用于分隔应用程序组件的模式。在 MVC 模式中,模型封装业务逻辑层,并与框架一块儿封装数据层。视图负责处理发送给客户机的数据表示。控制器的做用是控制应用程序流程。
扩 展 Web 应用程序的容量意味着让它可以处理更多的通讯流。容量扩展的一个方面是如何根据需求部署硬件。另外一个方面是应用程序如何响应新的硬件环境。从概念上说,在 出现性能问题时,每每首先想到使用功能更强的服务器;可是应用程序自己极可能形成其余瓶颈。把应用程序划分为一系列层有助于收缩问题的范围,能够简化容量 扩展。
如今先不考虑应用程序瓶颈。扩展应用程序的硬件一般有两种方式:水平扩展和垂直扩展。水平扩展意味着在一层中添加更多的服务器。在前面的示例中,应用服务器的瓶颈把请求速率限制在每秒 77 个请求,经过添加第二个应用服务器并在两个服务器之间共享负载,可能能够解决此问题。这会把理论容量提升到每秒 154 个请求,瓶颈位置就会转到数据库。
另外一方面,垂直扩展意味着使用功能更强的计算机。可使用功能更强的计算机运行应用服务器的两个实例,或者更快地处理请求。
初 看上去,您可能会彻底排除垂直扩展方式,由于购买多台小型计算机一般比不断购买更高级的服务器便宜。可是,在许多状况下,垂直扩展是更好的方法。若是您有 经过逻辑分区 (LPAR) 支持硬件分区的 IBM® Power® 服务器,就能够把空闲的容量添加到应用服务器层。
应用程序的需求也可能促使您选择垂直扩展。在一台服务器上很容易经过共享内存段共享用户的会话状态。若是使用两台服务器,就须要经过其余方式共享状态,好比数据库。数据库访问比内存访问慢,因此两台服务器的处理速度达不到一台服务器的两倍。
数据库是另外一个经常适合使用垂直扩展的场合。让数据集跨越不一样的服务器须要在应用程序层作大量工做,好比跨两个数据库联结列并确保数据是一致的。使用更强大的数据库服务器要容易得多,并且不须要经过从新构建应用程序来支持分散的数据。
根据前面对应用程序体系结构的讨论能够看出,Web 请求会经过多个阶段,每一个阶段花费必定的执行时间。请求排队经过每一个步骤,完成一个步骤以后,再排队进入下一个步骤。每一个步骤很像人们在商店里排队结账的状况。
能够把 Web 应用程序建模为一系列步骤(称为 “队列”)。应用程序的每一个组件都是一个队列。建模为一系列队列的典型 WebSphere 应用程序如图 3 所示。
图 3 显示请求等待 Web 服务器处理它们,而后等待 Web 容器,依此类推。若是进入某个队列的请求速率超过了此队列处理请求的速率,请求就会汇集起来。当出现请求汇集时,服务时间是不可预测的,用户会察觉到浏览器会话延迟。图 3 中的队列表明最糟糕的状况,由于 Web 服务器能够本身处理一些请求,即不须要访问数据库。
队 列在 UNIX® 环境中很常见。当应用程序发出磁盘请求的速率快于磁盘返回数据的速率时,操做系统会让磁盘请求排队,还可能调整请求的次序以下降寻道时间。另外一个队列是运 行队列,其中包含等待运行的进程的有序列表。应用程序会等待轮到它们使用某些有限的资源(好比 CPU)。
所以,队列调优是一种平衡的艺术。队列过小,就会在仍然有富余容量的状况下拒绝用户。队列太大,就会试图为过多的用户提供服务,致使性能不好。
导 致状况更复杂的另外一个因素是,这些排队位置并非无成本的。保留排队位置会致使内存开销,对于应用服务器,这会与正在处理请求的线程争用内存。所以,在一 般状况下,在应用服务器上排队并非好方法。推荐的方法是在应用服务器以前(好比在 Web 服务器上)排队。这意味着 Web 服务器要保持与 Web 客户机的链接,并在应用服务器空闲时发出请求。应用服务器只需处理它可以及时派发的请求。
IBM 的文档中推荐了 Web 应用程序布局方法和各类队列的调优方法。可是注意,IBM 建议应该避免在 WebSphere 中排队。这意味着应该把发送给 WebSphere 应用服务器的请求速率控制在可以当即处理的范围内。Web 服务器(或 Web 服务器前面的代理服务器)应该限制过多的链接,让它们等待处理。这确保负载比较重的应用服务器队列可以把时间花在为有限的请求提供服务上,而不是试图同时 为全部请求提供服务。
做为开发人员,应该按照一些通常原则提升应用程序的可伸缩性。这些原则能够应用于大多数 Web 应用程序。
应 用程序应该以某种方式向收集系统提供度量值(即便收集系统仅仅是日志文件)。这些度量值包括访问应用程序中某个函数的频率或处理一个请求花费的时间等。这 并不会使应用程序运行得更快,可是有助于了解应用程序为何会变慢以及代码的哪些部分花费的时间最长。了解何时调用某些函数,这有助于把在系统上观察 到的现象(好比 CPU 忙或磁盘活动量高)与应用程序中的活动(好比上传图像)联系起来。
可以了解站点上发生的状况,这是扩展站点容量的关键。您认为不够优化的代码部分可能不会形成问题。只有经过适当的度量,才能发现真正的瓶颈。
Web 在本质上是无状态的。用户发出的每一个请求都独立于之前的请求。可是,应用程序经常是有状态的。用户必须登陆应用程序以证实本身的身份,在访问站点期间可能 要维护购物车的状态,还可能要填写供之后使用的我的信息。跟踪会话是一种成本很高的操做,尤为是在涉及多个服务器的状况下。
在单 一服务器上运行的 Web 应用程序能够把会话信息放在内存中,在服务器上运行的任何 Web 应用程序实例均可以访问共享内存。经常会给用户分配一个标志,这个标志标识内存中的会话。考虑一下在涉及第二个应用服务器时会发生什么。若是用户的第一个 请求发送给一个服务器,第二个请求发送给另外一个服务器,那么会存在两个单独的会话,它们并不相同。
此问题的经常使用解决方案是,把会话存储在数据库而不是内存中。这种方法致使的问题是,对于每一个请求,须要增长数据库读操做,还可能涉及数据库写操做。每一个 Web 应用服务器都须要这个数据库。
一个解决方案是,只在须要会话的地方使用会话。应用程序并不为每一个请求装载会话,而是只在须要会话时装载会话。这会减小对后端数据库的请求数量。
另 一个方法是加密会话数据并把它发送回客户机,这样就不须要在本地存储会话。在用户的 cookie 中可以存储的数据量是有限的,可是 RFC 2109 规定客户机应该可以为每一个域名存储至少 20 个 cookie,每一个 cookie 至少能够保存 4K 字节的数据。
若是发现用数据库存储的会话是性能瓶颈,并且没法消除它们,那么应该考虑把它们分散到单独的数据库,甚至是多个数据库。例如,能够在一个数据库中存储偶数的会话 ID,在另外一个数据库中存储奇数的会话 ID。
与其余部分相比,应用程序的某些部分会更频繁地修改数据。新闻网站可能每月只修改顶级分类列表一次。所以,对于每一个请求都经过查询数据库获取最新的分类列表是很浪费的。一样,包含新闻稿的页面在其整个生命周期中可能只修改一两次,因此不须要为每一个请求从新生成它。
缓存意味着把处理成本很高的请求的结果存储起来,供之后使用。能够缓存分类列表或整个页面。
在考虑缓存时,问本身一个问题:“这些信息必须是最新的吗?” 若是不是这样,就能够考虑使用缓存。在新闻最初出现时,可以及时改变新闻稿可能很重要;可是在之后,每分钟检查一次修改并经过缓存提供页面,就足够了。
一种补充方法是,当底层数据改变时,让缓存的数据项失效。若是修改了新闻稿,在保存它时能够删除缓存的版本。对于下一个请求,因为没有缓存的版本,因此会生成新的数据项。
在使用缓存时,必须注意在缓存项过时或被删除时发生的状况。若是有许多请求在请求缓存项,那么在缓存项过时时,会为许多用户从新生成缓存项。为了解决这个问题,能够只为第一个请求从新生成缓存,而其余用户使用过期的版本,直到新的缓存项可用为止。
memcached 是一种流行的分布式内存缓存系统,在 UNIX 环境中部署的许多应用程序都使用它。服务器运行 memcache 守护进程的实例,这些进程分配一块能够经过一种简单的网络协议访问的 RAM。但愿在 memcache 中存储或获取数据的应用程序首先对键进行散列计算,这告诉它们应该使用 memcache 池中的哪一个服务器。而后,经过链接这个服务器检查或存储数据,这比磁盘或数据库访问快得多。
在寻找应该缓存的数据时,还应该考虑是否确实须要直接提供这些信息。须要在每一个页面上显示用户的购物车吗?只显示总金额怎么样?或者只显示一个简单的连接 “view the contents of your cart”。
Edge-Side Includes (ESI) 是一种标记语言,能够用它把网页划分为单独的可缓存的实体。应用程序负责生成包含 ESI 标记的 HTML 文档,还负责生成组件。Web 应用程序前面的代理缓存根据各个部分从新组装最终的文档,负责缓存一些组件并为其余组件发出请求。清单 1 给出一个 ESI 文档示例。
<html> <head> </head> <body> <p>This is static content</p> <esi:include src="/stories/123" /> <p>The line above just told the proxy to request /stories/123 and insert it in the middle of the page </p> </body> </html> |
尽管这个示例很是简单,可是 清单 1 说明了如何把两个文档拼接在一块儿,这两个文档有本身的缓存规则。
还 有一个问题与 “这些信息必须是最新的吗?” 相关:“必须在处理完请求时更新这些信息吗?” 在许多状况下,能够获取用户提交的数据并把处理延后几秒,而不须要在处理信息时让用户一直等待装载页面。这称为异步处理。一种经常使用方法是,让应用程序把数 据发送给一个消息队列,好比 IBM WebSphere MQ,等待到资源可用时处理数据。这样就能够当即把一个页面返回给用户,尽管数据处理的结果仍是未知的。
请考虑一个电子商务应用 程序,用户会在这个程序中提交订单。当即返回信用卡检验结果多是很重要的,可是不须要让订单系统立刻确认订单的全部内容都是有效的。能够把订单放进一个 队列中等待处理,这可能会在几秒内发生。若是发生了错误,能够经过电子邮件通知用户,若是用户仍然在网站上,甚至能够把错误通知插入他的会话。另外一个示例 是报告。不须要让用户一直等待生成报告,而是能够返回 “please check the reports page in a few minutes” 消息,同时在另外一台服务器上异步地生成报告。
应用程序经常采用分层方式编写。表示逻辑与业务逻辑分隔开,业务逻辑又与持久化存储分隔开。这种方式能够提升代码的可维护性,可是也会致使一些开销。在扩展应用程序的容量时,应该了解数据在分层环境中的流动并寻找出现瓶颈的位置。
缓存和异步处理等技术能够重用之前的结果或把工做转移到另外一台计算机上,从而下降应用程序的工做负载。在应用程序中提供度量设施,有助于及时了解 “热点”。
应用服务器环境的工做方式与排队网络很类似,必定要仔细地管理队列的大小,确保一层不会对另外一层施加过大的压力。IBM 建议尽量在应用服务器以前排队,好比在外部 Web 服务器或代理服务器上。
仅仅靠投入更多的硬件,不多可以有效地扩展应用程序的容量。经常须要综合应用这些技术,才能让新的硬件发挥做用。