《大型网站技术架构――核心原理与案例分析》读书笔记(4)

第四章 网站的高性能架构


  网站性能是客观的指标,可以具体体现到响应时间,吞吐量等技术指标,同时也是主观的感受,而感受则是一种与具体参与者相关的微妙的东西,用户的感受和工程师的感受不同,不同的用户感受也不同。


一、 网站性能测试

  性能测试是性能优化的前提和基础,也是性能优化结果的检查和度量标准。不同视角下的网站性能有不同的标准,也有不同的优化手段。

  1. 不同视角下的网站性能

  (1) 用户角度,网站性能就是用户在浏览器上直观感受到的网站响应速度快还是慢。主要优化手段:优化页面HTML样式,利用浏览器端的并发和异步特性,调整浏览器缓存策略,使用CDN服务,反向代理等。

  (2) 开发人员角度,关注的主要是应用程序本身及其相关子系统的性能,包括响应延迟,系统吞吐量,并发处理能力,系统稳定性等技术指标。主要优化手段:使用缓存加速数据读取,使用集群提高吞吐能力,使用异步消息加快请求响应及实现削峰,使用代码优化手段改善程序性能等。

  (3) 运维人员角度,关注基础设施性能和资源利用率,如网络运营商的带宽能力,服务器硬件的配置,数据中心网络架构,服务器和网络带宽的资源利用率等。主要优化手段:建设优化骨干网,使用高性价比定制服务器,利用虚拟化技术优化资源利用等。

  2. 性能测试指标

  (1) 响应时间 

  指应用执行一个操作需要的时间,包括从发出请求开始到收到最后响应数据所需要的时间。

  (2) 并发数 

  指系统能够同时处理请求的数目,也反映了系统的负载特性。

  (3) 吞吐量 

  指单位时间内系统处理的请求数量,体现系统的整体处理能力。如:TPS(每秒事务数)是吞吐量的一个常用量化标准,HPS(每秒HTTP请求数),QPS(每秒查询数)等。在系统并发数由小逐渐增大的过程中(这个过程中也伴随着服务器系统资源消耗逐渐增大),系统吞吐量先是逐渐增加,达到一个极限后,随着并发数的增加反而下降,达到系统崩溃点后,系统资源耗尽,吞吐量均为零。而这个过程中,响应时间则是保持小幅上升,到达吞吐量极限后,快速上升,到到系统崩溃点后,系统失去响应。

  (4) 性能计数器 

  描述服务器或操作系统性能的一些数据指标。包括System Load,对象与线程数,内存使用,CPU使用,磁盘与网络IO等指标。

  System Load即系统负载,指当前正在被CPU执行和等待被CPU执行的进程数目总和,是反映系统忙闲程度的重要指标。多核CPU的情况下,完美情况是所有CPU都在使用,没有进程在等待处理。所以Load的理想值是CPU的数目。当Load值低于CPU数目的时候,表示CPU有空闲,资源存在浪费;当Load值高于CPU数目的时候,表示进程在排队等候CPU调度,表示系统资源不足,影响应用程序的执行性能。在Linux系统中使用top命令查看。

  3. 性能测试方法

  性能测试:以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能瓶颈。

  负载测试:对系统不断地增加并发请求以增加系统压力,直到系统的某项或多项性能指标达到安全临界值,如某种资源已经呈饱和状态,这是继续对系统施加压力,系统的处理能力不但不能提高,反而会下降。

  压力测试:超过安全负载的情况下,对系统继续施加压力,直到系统崩溃或不能再处理任何请求,以此获得系统最大压力承受能力。

  稳定性测试:被测试系统在特定硬件,软件,网络环境条件下,给系统加载一定业务压力,使系统运行一段较长时间,以此检测系统是否稳定。在不同生产环境,不同时间点的请求压力是不均匀的,呈波浪特性,因此为了更好地模拟生产环境,稳定性测试也应不均匀地对系统施加压力。

  4. 性能测试报告

  测试结果报告应能够反映性能测试曲线的规律,阅读者可以得到系统性能是否满足设计目标和业务要求、系统最大负载能力、系统最大压力承受能力等重要信息。

  5. 性能优化策略

如果性能测试结果不能满足设计或业务需求,那么就需要寻找系统瓶颈,分而治之,逐步优化。

  (1) 性能分析

  大型网站结构复杂,用户从浏览器发出请求直到数据库完成操作事务,中间需要经过很多环节,如果测试或者用户报告网站响应缓慢,存在性能问题,必须对请求经历的各个环节进行分析,排查可能出现性能瓶颈的地方,定位问题。

  排查一个网站的性能瓶颈和排查一个程序的性能瓶颈的手法基本相同:检查请求处理的各个环节的日志,分析哪个环节响应时间不合理、超过预期;然后检查监控数据,分析影响性能的主要因素是内存、磁盘、网络、还是CPU,是代码问题还是架构设计不合理,或者系统资源确实不足。

  (2) 性能优化

  定位产生性能问题的具体原因后,就需要进行性能优化,根据网站分层架构,可分为Web前端性能优化、应用服务器性能优化、存储服务器性能优化3大类。


二、 Web前端性能优化

  1. 浏览器访问优化

  (1) 减少HTTP请求 

  每次HTTP请求都需要建立通信链路,进行数据传输,而在服务器端,每个HTTP都需要启动独立的线程去处理。这些通信和服务的开销都是很昂贵,减少HTTP请求的数目可有效提高访问性能。

  减少HTTP的主要手段:合并CSS,合并JavaScript,合并图片。将浏览器一次访问需要的JavaScript,CSS合并成一个文件,这样浏览器只需要一次请求。图片也可以合并,多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS偏移响应鼠标点击操作,构造不同的URL。

  (2) 使用浏览器缓存 

  通过设置HTTP头中Cache-Control和Expires的属性,可设定浏览器缓存,缓存时间可以是数天,甚至是几个月。

  在某些时候,静态资源文件变化需要及时应用到客户端浏览器,这种情况,可通过改变文件名实现,即更新JavaScript文件不是更新JavaScript文件内容,而是生成一个新的JS文件并更新HTML文件中的引用。

  使用浏览器缓存策略的网站在更新静态资源时,不应采用批量更新的方法,比如需要更新10个图标文件,不宜把10个文件一次全部更新,而是一个文件一个文件逐步更新,并有一定的间隔时间,以免用户浏览器突然大量缓存失效,集中更新缓存,造成服务器负载骤增,网络堵塞的情况。

  (3) 启用压缩 

  在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。文本文件的压缩效率可达80%以上,因此HTML,CSS,JavaScript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信带宽良好,而服务器资源不足的情况下要权衡考虑。

  (4) CSS放在页面最上面,JavaScript放在页面最下面 

  浏览器会在下载完全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载。JavaScript则相反,浏览器在加载JavaScript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此JavaScript最好放在页面最下面。但如果页面解析时就需要用到JavaScript,这时放在底部就不合适了。

  (5) 减少Cookie传输 

  一方面,Cookie包含在每次请求和响应中,太大的Cookie会严重影响数据传输,因此哪些数据需要写入Cookie需要慎重考虑,尽量减少Cookie中传输的数据量。另一方面,对于某些静态资源的访问,如CSS,JavaScript等,发送Cookie没有意义,可以考虑静态资源使用独立域名,避免请求静态资源时发送Cookie,减少Cookie传输的次数。

  2. CDN加速

  CDN(内容分发网络)的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳。

  CDN能够缓存的一般是静态资源,如图片,文件,CSS,JavaScript脚本,静态网页等,但是这些文件访问频度很高,将其缓存在CDN可极大改善网页的打开速度。

  3. 反向代理

  反向代理服务器位于网站机房一侧,代理网站Web服务器接收HTTP请求。

  反向代理服务器也具有保护网站安全的作用,来自互联网的访问请求必须经过代理服务器,相当于在Web服务器和可能的网络攻击之间建立了一个屏障。

  代理服务器也可以通过配置缓存功能加速Web请求。当用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上,这样当其他用户访问该静态内容的时候,就可以直接从反向代理服务器返回,加速Web请求响应速度,减轻Web服务器负载压力。

  反向代理也可以实现负载均衡的功能,而通过负载均衡构建的应用集群可以提高系统总体处理能力,进而改善网站高并发情况下的性能。


三、 应用服务器性能优化

  1. 分布式缓存

  网站性能优化第一定律:优先考虑使用缓存优化性能。分布式缓存指缓存部署在多个服务器组成的集群中,以集群方式提供缓存服务。合理使用缓存,注意一下几点: 

  (1) 避免缓存频繁修改的数据:如果缓存中保存的是频繁修改的数据,就会出现数据写入缓存后,应用还来不及读取缓存,数据就已失效的情形,陡增系统负担。

  (2) 避免缓存没有热点的数据:由于内存空间有限,只能将最新访问的数据缓存起来,而将历史数据清理出缓存。如果应用系统访问数据没有热点,即大部分数据访问并没有集中在小部分数据上,那么缓存就没有意义,因为大部分数据还没有被再次访问就已经被挤出缓存了。 

  (3) 数据不一致与脏读:对缓存的数据设置失效时间,一旦超过失效时间,就要从数据库中重新加载,应用要容忍一定时间的数据不一致。 

  (4) 缓存可用性:缓存是为提高数据读取性能的,缓存数据丢失或者缓存不可用不会影响到应用程序的处理――它可以从数据库直接获取数据。但当缓存服务器崩溃时,数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况被称作缓存雪崩。缓存根本就不应该被当做一个可靠的数据源来使用。通过分布式缓存服务器集群,将缓存数据分布到集群多台服务器上可在一定程度上改善缓存的可用性。 

  (5) 缓存预热:缓存中存放的是热点数据,热点数据又是缓存系统利用LRU(最近最久未用算法)对不断访问的数据筛选淘汰出来的,这个过程需要花费较长的时间。新启动的缓存系统如果没有任何数据,在重建缓存数据的过程中,系统的性能和数据库负载都不太好,那么最好在缓存系统启动时就把热点数据加载好,这个缓存预加载手段叫作缓存预热。 

  (6) 缓存穿透:缓存没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大压力,甚至崩溃。一个简单的对策就是将不存在的数据也缓存起来(其value值为null)。

  2. 异步操作

  消息队列具有很好的削峰作用――即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。任何可以晚点做的事情都应该晚点做。

  3. 使用集群

  在网站高并发的情况下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。

  4. 代码优化

  (1) 多线程 

  多用户并发访问是网站的基本要求, 解决线程安全的主要手段有如下几点:将对象设计为无状态对象;使用局部对象;并发访问资源时使用锁;

  (2) 资源复用 

  系统运行时,要尽量减少那些开销很大的系统资源的创建和销毁,比如数据库连接,网络通信连接,线程,复杂对象等。从编程角度,资源复用主要有两种模式:单例(Singleton)和对象池(Object Pool)。

  (3) 数据结构 

  在不同场景中合理使用恰当的数据结构,灵活组合各种数据结构改善数据读写和计算特性可极大优化程序的性能。

  (4) 垃圾回收 

  根据系统业务特点和对象生命周期,合理设置Young Generation和Old Generation大小,尽量减少Full GC。事实上,某些Web应用在整个运行期间可以做到从不进行Full GC。


四、存储性能优化

  很多时候,磁盘仍然是系统最严重的瓶颈,而且磁盘中存储的数据是网站最重要的资产,磁盘的可用性和容错性也至关重要。

  1. 机械硬盘 VS 固态硬盘

  机械硬盘:快速顺序访问,慢速随机访问

  固态硬盘:快速随机访问

  2. B+树 VS LSM树

  磁盘的读写特性对存储结构和算法的选择影响深大。 

  B+树:是一种专门针对磁盘存储而优化的N叉排序树,以树节点为单位存储在磁盘中,从根开始查找所需数据所在的节点编号和磁盘位置,将其加载到内存中然后继续查找,直到找到所需的数据。但是由于每次磁盘访问都是随机的,而传统机械硬盘在数据随机访问时性能较差,每次数据访问都需要多次访问磁盘影响数据数据访问性能。

  LSM树:在需要进行读操作时,总是从内存中的排序树开始搜索,如果没有找到,就从磁盘上的排序树顺序查找。在LSM树上进行一次数据更新不需要磁盘访问,在内存即可完成,速度远快于B+树。当数据访问以写操作为主,而读操作则集中在最近写入的数据上时,使用LSM树可以极大程序地减少磁盘的访问次数,加快访问速度。

  3. RAID VS HDFS

  RAID(廉价磁盘冗余阵列)技术主要是为了改善磁盘的访问延迟,增强磁盘的可用性和容错能力。RAID技术在传统关系数据库及文件系统中应用比较广泛,但是在大型网站比较喜欢使用的NoSQL,以及分布式文件系统中,RAID技术却遭到冷落。

  HDFS(Hadoop分布式文件系统):HDFS配合MapReduce等并行计算框架进行大数据处理时,可以在整个集群上并发读写访问所有的磁盘,无需RAID支持。


五、思维导图

  来自:http://www.cnblogs.com/leo_wl/p/3812115.html

《大型网站技术架构――核心原理与案例分析》读书笔记(4)_第1张图片

你可能感兴趣的:(大型网站,技术架构)