共计 6295 个字符,预计需要花费 16 分钟才能阅读完成。
性能是主观的指标,能够具体到响应工夫、吞吐量等技术指标,同时也是主观的感触,用户的感触和工程师的感触不同,不同的用户感触也不同。
性能测试
性能测试指标
不同视角下有不同的性能规范,不同的规范有不同的性能测试指标,罕用的指标有如下几个:
- 响应工夫:指利用执行一个操作须要的工夫,包含从发出请求开始到收到最初响应数据所须要的工夫。响应工夫是零碎最重要的性能指标,直观地反映了零碎的“快慢”。
- 并发数:指零碎可能同时解决申请的数目,这个数字也反映了零碎的负载个性。
- 吞吐量:指单位工夫内零碎解决的申请数量,体现零碎的整体解决能力。
性能测试方法
性能测试具体可细分为性能测试、负载测试、压力测试、稳定性测试。
性能测试是一个一直对系统减少拜访压力,以取得零碎性能指标、最大负载能力的过程。所谓的减少拜访压力,在零碎测试环境中,就是一直减少测试程序的并发申请数,一般说来,性能测试遵循如图所示的抛物线法则。
在开始阶段,随着并发申请数目的减少,零碎应用较少的资源就达到较好的解决能力(a~b 段),这一段是网站的日常运行区间,网站的绝大部分拜访负载压力都集中在这一段区间,被称作性能测试,测试指标是评估零碎性能是否合乎需要及设计指标。
随着压力的继续减少,零碎解决能力减少变缓,直到达到一个最大值(c 点),这是零碎的最大负载点,这一段被称作负载测试。测试指标是评估当零碎因为突发事件超出日常拜访压力的状况下,保证系统失常运行状况下可能接受的最大拜访负载压力。
超过这个点后,再减少压力,零碎的解决能力反而降落,而资源耗费却更多,直到资源耗费达到极限(d 点),这个点能够看作是零碎的崩溃点,超过这个点持续加大并发申请数目,零碎不能再解决任何申请,这一段被称作压力测试,测试指标是评估可能导致系统解体的最大拜访负载压力。
性能优化策略
如果零碎存在性能问题,必须对申请经验的各个环节进行剖析,排查可能呈现性能瓶颈的中央,定位问题。
排查一个网站的性能瓶颈和排查一个程序的性能瓶颈的手法基本相同:查看申请解决的各个环节的日志,剖析哪个环节响应工夫不合理、超过预期;而后查看监控数据,剖析影响性能的次要因素是内存、磁盘、网络、还是 CPU,是代码问题还是架构设计不合理,或者系统资源的确有余。
定位产生性能问题的具体起因后,就须要进行性能优化,依据网站分层架构,可分为 Web 前端性能优化、应用服务器性能优化、存储服务器性能优化 3 大类。
Web 前端性能优化
一般说来 Web 前端指网站业务逻辑之前的局部,包含浏览器加载、网站视图模型、图片服务、CDN 服务等,次要优化伎俩有优化浏览器拜访、应用反向代理、CDN 等。
浏览器拜访优化
缩小 http 申请
HTTP 协定是无状态的应用层协定,意味着每次 HTTP 申请都须要建设通信链路、进行数据传输,而在服务器端,每个 HTTP 都须要启动独立的线程去解决。这些通信和服务的开销都很低廉,缩小 HTTP 申请的数目可无效进步拜访性能。
缩小 HTTP 的次要伎俩是合并 CSS、合并 JavaScript、合并图片。将浏览器一次拜访须要的 JavaScript、CSS 合并成一个文件,这样浏览器就只须要一次申请。图片也能够合并,多张图片合并成一张,如果每张图片都有不同的超链接,可通过 CSS 偏移响应鼠标点击操作,结构不同的 URL。
应用浏览器缓存
对一个网站而言,CSS、JavaScript、Logo、图标这些动态资源文件更新的频率都比拟低,如果将这些文件缓存在浏览器中,能够极好地改善性能。通过设置 HTTP 头中 Cache-Control 和 Expires 的属性,可设定是否开启浏览器缓存以及缓存工夫。
动态资源文件变动须要及时利用到客户端浏览器,这种状况,可通过扭转文件名实现,即 生成一个新的 JS 文件并更新 HTML 文件中的援用。在更新动态资源时,应采纳批量更新的办法,并有肯定的间隔时间,免得用户浏览器忽然大量缓存生效,集中更新缓存,造成服务器负载骤增、网络拥塞的状况。
启用压缩
在服务器端对文件进行压缩,在浏览器端对文件解压缩,可无效缩小通信传输的数据量。然而 压缩对服务器和浏览器产生肯定的压力,在通信带宽良好,而服务器资源有余的状况下要衡量思考。
缩小 Cookie 传输
一方面,Cookie 蕴含在每次申请和响应中,太大的 Cookie 会重大影响数据传输,因而哪些数据须要写入 Cookie 须要慎重考虑,尽量减少 Cookie 中传输的数据量。
另一方面,对于某些动态资源的拜访,如 CSS、Script 等,发送 Cookie 没有意义,能够思考动态资源应用独立域名拜访,防止申请动态资源时发送 Cookie,缩小 Cookie 传输的次数。
CDN 减速
CDN(Content Distribute Network,内容散发网络)的实质依然是一个缓存,而且将数据缓存在离用户最近的中央,使用户以最快速度获取数据。
因为 CDN 部署在网络运营商的机房,这些运营商又是终端用户的网络服务提供商,因而用户申请路由的第一跳就达到了 CDN 服务器,当 CDN 中存在浏览器申请的资源时,从 CDN 间接返回给浏览器,放慢用户访问速度,缩小数据中心负载压力。
反向代理
反向代理服务器位于网站机房一侧,代理网站 Web 服务器接管 HTTP 申请。反向代理服务器具备爱护网站平安的作用,除了平安性能,代理服务器也能够通过配置缓存性能减速 Web 申请。
当用户第一次拜访动态内容的时候,动态内容就被缓存在反向代理服务器上,这样当其余用户拜访该动态内容的时候,就能够间接从反向代理服务器返回,减速 Web 申请响应速度。有些网站会把某些热门的动静内容也缓存在代理服务器上,当这些动静内容有变动时,通过外部告诉机制告诉反向代理缓存生效,反向代理会从新加载最新的动静内容再次缓存起来。
此外,反向代理也能够实现负载平衡的性能,进而改善网站高并发状况下的性能。
应用服务器性能优化
应用服务器就是解决网站业务的服务器,网站的业务代码都部署在这里,优化伎俩次要有缓存、集群、异步等。
缓存
性能优化第一定律:优先思考应用缓存优化性能。缓存指将数据存储在绝对较高访问速度的存储介质中,以供零碎解决。
应用策略
应用缓存的首要前提就是存在热点数据,如果不存在热点拜访,那么会呈现大部分数据还没有被再次拜访就被挤出缓存。而且 须要缓存的数据读写比必须足够高,数据的读写比至多应该在 2:1 以上,缓存才有意义。
数据不统一
个别会对缓存的数据设置生效工夫,一旦超过生效工夫,就要从数据库中从新加载。因而利用要容忍肯定工夫的数据不统一。在互联网利用中,这种提早通常是能够承受的,然而具体利用仍需慎重对待。还有一种策略是数据更新时立刻更新缓存,不过这也会带来更多零碎开销和事务一致性的问题。
缓存预热
新启动的缓存零碎如果没有任何数据,在构建缓存数据的过程中,零碎的性能和数据库负载都不太好,那么最好在缓存系统启动时就把热点数据加载好,这个缓存预加载伎俩叫作缓存预热。
缓存可用性
随着业务的倒退,缓存会承当大部分数据拜访的压力,当缓存服务解体时,数据库会因为齐全不能接受如此大的压力而宕机,进而导致整个网站不可用。
通过分布式缓存服务器集群,将缓存数据散布到集群多台服务器上可在肯定水平上改善缓存的可用性。当一台缓存服务器宕机的时候,只有局部缓存数据失落,从新从数据库加载这部分数据不会对数据库产生很大影响。
缓存穿透
如果因为不失当的业务、或者歹意攻打继续高并发地申请某个不存在的数据,因为缓存没有保留该数据,所有的申请都会落到数据库上,会对数据库造成很大压力,甚至解体。一个简略的对策是将不存在的数据(null)也缓存起来,亦或是应用布隆过滤器。
异步
应用音讯队列将调用异步化,可改善零碎的扩展性,同时也能够改善零碎性能。因为音讯队列服务器处理速度远快于数据库(音讯队列服务器也比数据库具备更好的伸缩性),用户的响应提早可失去无效改善,并且能够升高数据库的负载压力。
音讯队列具备很好的削峰作用——即 通过异步解决,将短时间高并发产生的事务音讯存储在音讯队列中,从而削平高峰期的并发事务。在电子商务网站促销流动中,正当应用音讯队列,可无效抵挡促销流动刚开始大量涌入的订单对系统造成的冲击。
须要留神的是,因为数据写入音讯队列后立刻返回给用户,数据在后续的业务校验、写数据库等操作可能失败,因而在应用音讯队列进行业务异步解决后,须要适当批改业务流程进行配合。如订单提交后,订单数据写入音讯队列,不能立刻返回用户订单提交胜利,须要在音讯队列的订单消费者过程真正解决完该订单,甚至商品出库后,再通过电子邮件或 SMS 音讯告诉用户订单胜利,免得交易纠纷。
注:任何能够晚点做的事件都应该晚点再做。
集群
在高并发拜访的场景下,应用负载平衡技术为一个利用构建一个由多台服务器组成的服务器集群,将并发拜访申请散发到多台服务器上解决,防止繁多服务器因负载压力过大而响应迟缓,使用户申请具备更好的响应提早个性。
代码优化
理优化业务代码,能够很好地改善零碎性能。代码优化伎俩有很多,这里咱们概要地关注比拟重要的几个方面。
多线程
多用户并发拜访是利用零碎的根本需要,大型网站的并发用户数会达到数万,单台服务器的并发用户也会达到数百。从资源利用的角度看,应用多线程的起因次要有两个:IO 阻塞与多 CPU。
网站的应用程序个别都被 Web 服务器容器治理,用户申请的多线程也通常被 Web 服务器容器治理,但不论是 Web 容器治理的线程,还是应用程序本人创立的线程,一台服务器上启动多少线程适合呢?假如服务器上执行的都是雷同类型工作,针对该类工作启动的线程数有个简化的估算公式可供参考:启动线程数 = [工作执行工夫 /(工作执行工夫 -IO 等待时间)] × CPU 内核数。
多线程编程一个须要留神的问题是线程平安问题,也即同步问题。解决线程平安的次要伎俩有应用无状态对象和部分对象(不共享数据)以及应用锁等。
资源复用
零碎运行时,要尽量减少那些开销很大的系统资源的创立和销毁,比方数据库连贯、网络通信连贯、线程、简单对象等。从编程角度,资源复用次要有两种模式:单例(Singleton)和对象池(ObjectPool)。
单例尽管是 GoF 经典设计模式中被较多诟病的一个模式,但因为目前 Web 开发中次要应用贫血模式,从 Service 到 Dao 都是无状态对象,无需反复创立,这种状况下应用单例模式也就很天然了。
对象池模式通过复用对象实例,缩小对象创立和资源耗费。所谓的连接池、线程池,实质上都是对象池,池治理形式也基本相同。
垃圾回收
当初的主力编程语言如 Java、PHP、Golang 等都具备主动垃圾回收性能,垃圾回收可能会对系统的性能个性产生微小影响。了解所应用的编程语言的垃圾回收机制有助于程序优化和参数调优,以及编写内存平安的代码。
存储性能优化
在利用零碎中,海量的数据读写对磁盘拜访造成微小压力,尽管能够通过 Cache 解决一部分数据读压力,然而磁盘依然是零碎最重大的瓶颈。
机械硬盘和固态硬盘
机械硬盘是目前最罕用的一种硬盘,通过马达驱动磁头臂,带动磁头到指定的磁盘地位拜访数据。机械硬盘在数据间断拜访和随机拜访时,性能差异十分大。
固态硬盘没有机械安装,数据存储在可长久记忆的硅晶体上,因而能够像内存一样疾速随机拜访。在利用零碎中,大部分数据拜访都是随机的,这种状况下 SSD 具备更好的性能体现。
B+ 树和 LSM 树
为了改善数据拜访个性,文件系统或数据库系统通常会对数据排序后存储,放慢数据检索速度,这就须要保证数据在不断更新、插入、删除后仍然有序,传统关系数据库的做法是应用 B + 树,如图所示。
B+ 树是一种专门针对磁盘存储而优化的 N 叉排序树,以树节点为单位存储在磁盘中,从根开始查找所需数据所在的节点编号和磁盘地位,将其加载到内存中而后持续查找,直到找到所需的数据。
目前许多 NoSQL 产品采纳 LSM 树作为次要数据结构,如图所示。
LSM 树能够看作是一个 N 阶合并树。数据写操作都在内存中进行,并且都会创立一个新记录(批改会记录新的数据值,而删除会记录一个删除标记),这些数据在内存中依然还是一棵排序树,当数据量超过设定的内存阈值后,会将这棵排序树和磁盘上最新的排序树合并。当这棵排序树的数据量也超过设定阈值后,和磁盘高低一级的排序树合并。合并过程中,会用最新更新的数据笼罩旧的数据(或者记录为不同版本)。
在须要进行读操作时,总是从内存中的排序树开始搜寻,如果没有找到,就从磁盘上的排序树程序查找。
在 LSM 树上进行一次数据更新不须要磁盘拜访,在内存即可实现,速度远快于 B + 树。当数据拜访以写操作为主,而读操作则集中在最近写入的数据上时,应用 LSM 树能够极大水平地缩小磁盘的拜访次数,放慢访问速度。
延长浏览:【分布式—根底】数据存储与检索
RAID
RAID(便宜磁盘冗余阵列)技术次要是为了改善磁盘的拜访提早,加强磁盘的可用性和容错能力。目前服务器级别的计算机都反对插入多块磁盘,通过应用 RAID 技术,实现数据在多块磁盘上的并发读写和数据备份。罕用 RAID 技术有以下几种,如图所示。
RAID 0
数据在从内存缓冲区写入磁盘时,依据磁盘数量将数据分成 N 份,这些数据同时并发写入 N 块磁盘,使得数据整体写入速度是一块磁盘的 N 倍。读取时也一样,因而 RAID0 具备极快的数据读写速度,然而 RAID0 不做数据备份,N 块磁盘中只有有一块损坏,数据完整性就被毁坏,所有磁盘的数据都会损坏。
RAID 1
数据在写入磁盘时,将一份数据同时写入两块磁盘,这样任何一块磁盘损坏都不会导致数据失落,插入一块新磁盘就能够通过复制数据的形式主动修复,具备极高的可靠性。
RAID 10
联合 RAID0 和 RAID1 两种计划,将所有磁盘均匀分成两份,数据同时在两份磁盘写入,相当于 RAID1,然而在每一份磁盘外面的 N / 2 块磁盘上,利用 RAID0 技术并发读写,既进步可靠性又改善性能,不过 RAID10 的磁盘利用率较低,有一半的磁盘用来写备份数据。
RAID 3
个别状况下,一台服务器上不会呈现同时损坏两块磁盘的状况,在只损坏一块磁盘的状况下,如果能利用其余磁盘的数据恢复损坏磁盘的数据,这样在保障可靠性和性能的同时,磁盘利用率也失去大幅晋升。
在数据写入磁盘的时候,将数据分成 N - 1 份,并发写入 N - 1 块磁盘,并在第 N 块磁盘记录校验数据,任何一块磁盘损坏(包含校验数据磁盘),都能够利用其余 N - 1 块磁盘的数据修复。
然而在数据批改较多的场景中,批改任何磁盘数据都会导致第 N 块磁盘重写校验数据,频繁写入的结果是第 N 块磁盘比其余磁盘容易损坏,须要频繁更换,所以 RAID3 很少在实践中应用。
RAID 5
RAID5 和 RAID3 很类似,然而校验数据不是写入第 N 块磁盘,而是螺旋式地写入所有磁盘中。这样校验数据的批改也被均匀到所有磁盘上,防止 RAID3 频繁写坏一块磁盘的状况。
RAID 6
如果数据须要很高的可靠性,在呈现同时损坏两块磁盘的状况下,依然须要修复数据,这时候能够应用 RAID6。RAID6 和 RAID5 相似,然而数据只写入 N - 2 块磁盘,并螺旋式地在两块磁盘中写入校验信息(应用不同算法生成)。
各种 RAID 技术的比拟如下表所示。
RAID 类型 | 访问速度 | 数据可靠性 | 磁盘利用率 |
---|---|---|---|
RAID0 | 很快 | 很低 | 100% |
RAID1 | 很慢 | 很高 | 50% |
RAID10 | 中等 | 很高 | 50% |
RAID5 | 较快 | 较高 | (N – 1)/ N |
RAID6 | 较快 | 较高 | (N – 2)/ N |
RAID 技术能够通过硬件实现,比方专用的 RAID 卡或者主板间接反对,也能够通过软件实现。RAID 技术在传统关系数据库及文件系统中利用比拟宽泛,然而在大型网站比拟喜爱应用的 NoSQL,以及分布式文件系统中,RAID 技术却受到冷清。