引言
最新中国互联网络信息中心(CNNIC)发布的《第38次中国互联网络发展状况统计报告》,2016年6月,我国网民规模达7.1亿。全球互联网网站数量超过10亿个。如此多的设备,如此吸引用户的在线服务,如何做到脱颖而出,除了产品本身的设计外,你的产品能不能比其他产品更快的响应的用户也是非常关键的因素。有数据表明,移动互联网下用户越来越没有耐心,用户越来越重视速度方面的用户体验,很多互联网公司的业绩已经证实:网站越快,用户的粘性越高、网站越快,用户忠诚度越高、网站越快,用户转化率越高。在当今转移成本如此之地低的情况大环境下,用户除非别无选择,否则,用户动动手指就离开了,任何好的架构和产品设计都离不开高性能的支撑。
Web的本意是蜘蛛网和网的意思,在网页设计中我们称为网页的意思。现广泛译作网络、互联网等技术领域。它的表现形式可以是通过浏览器访问的网站、内嵌H5、或者后端提供的RESTful API等,本文指的Web泛指通过Web技术提供的互联网服务,不仅限于网站。关于架构,百科上的定义是“是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计”。本文将从新的的角度、以及如何利用新技术等分析和阐述如何打造高性能的 Web 架构。
网络
Web运行原理
Web 前端浏览器运行机制:
Web 后端服务架构运行机制:
通过以上两张图可以清晰看出不管是在 Web 前端架构运行机制还是 Web 后端架构中,网络已经成了必不可少且非常重要的地位。用户通过网络访问 Web 服务器,Web 后端架构中各种服务之间通过网络来进行通信和协作,网络是现代 Web 应用的基石,因此在谈到高性能架构时候不得不从网络谈起。
协议对性能的影响
TCP
TCP 是一种面向连接的、可靠的、基于字节流的传输层通信协议,是几乎现在所有网络应用的基础协议,所有需要可靠性网络通信的应用都受TCP协议本身的影响和制约。TCP本身是一个非常棒的协议,协议本身为了保障信息的可靠性(保证信息送达)发展出了许许多多的严密而复杂的机制来进行保障,但是可靠性的反面就必然会牺牲性能和效率,下面简要介绍几个机制:
三次握手:TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK,并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接。
简单的说就是建立TCP的网络连接本身至少需要3个来回(在正式发送数据之前),如果单程需要30ms,建立连接操作就需要 90ms(毫秒)。
慢启动:在连接建立后,这时我们开始传输数据,但这里存在一个问题,我们传送多少数据合适的问题,如果传的太多了,对方可能无法处理(入网带宽过小、或者计算机正在干别的操作被占用等),如果多对方无法处理的数据给整个互联网其实是占用不必要的堵塞和占用,TCP为了解决问题有一个机制叫慢热启动。慢启动的意思是,刚刚开始传输数据的时候,一点一点地提速,不要一上来就像那些特权车一样霸道地把路占满。这么说还是不太直观,下面举个例子: 服务器的出口带宽是100MB,用户的入网带宽是20MB,按照以上数据来说,用户可以接受的最大下载数据量是 2.5MB/S,但是为了整个网络社会的和谐,初始的时候的时候服务器和用户都不会以 2.5MB/S 以起始像对方传输数据,而是以1460字节开始(MSS),并且随着对方的ACK回应包这个可以传输的数量乘以指数增长,直到达到最高数(ssthresh);如果发生丢包,这个传输量将会以指数级下降;如果网络被闲置,哪怕刚才已经达到了最高的 2.5MB/S速度,将又会从最小值开始试探性传输数据(实际机制比这个更复杂涉及各种情况判断变换算法)。
拥塞窗口:TCP拥塞控制中的一个概念:指源端在拥塞控制情况下一次最多能发送的数据包的数量。发送端根据网络的拥塞程度所预设的一个大小值,而这个值就是拥塞窗口。上面的慢启动其实就是通过拥塞窗口来控制的,MSS (cwnd N),MSS为传输的最小单元,N为拥塞窗口的数量,通过增减窗口的数量来控制发送的数据量。这其中还会有一个问题,就是窗口的大小是有限制,TCP的每个数据数组都需要被对方确认后才会完成,这时候无论是发送端还是接收端的数据只要超过了未确认的最大数量,就必须停下来等待另一方的ACK确认这些数据分组才能继续,否则服务器只能干等着无法传送数据。
丢包重传:TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。这里说的是对于任何一个发送的数据包,对方都需要回应一个确认包,表示数据收到了,也就是哪怕正常网络情况下,每一次数据包发送都意味至少的两次网络数据交换。这是一个很好从机制,但是只要发现丢包就会导致重传,那么如果用户离你比较远或者访问你的网络服务中间任意节点不稳定的话,那将会导致频繁的重新重复发送同一份数据,因此网络质量越差越不稳定,你响应用户的时间就越长,因为大部分时间可能耗费在重复给用户发送数据上。
HTTP
不管是服务器之间近距离传输通信,还是用户请求网页如果使用 TCP 协议都要受以上流程和机制影响。TCP就在OSI模型的第四层传输层,HTTP运行在第七层应用层,由于分层是单向依赖的,所以HTTP必然依赖于TCP协议来运行,所有 TCP 有的问题同样 HTTP 全部都会继承。同时HTTP在此基础上也有自己的协议规则,比如说浏览器最大和服务器建立的连接数: HTTP协议也有非常多的规则,其中不同的浏览器实现也并非完全一样,在不同的HTTP版本下,也有实现上的差别,下图就是每个浏览器对应的可以同时发起请求的个数,意味着如果能同时请求的文件数,一般网页平均有90个文件,如果每次只能请求2~6个文件,那效率肯定不会很高。
在某些浏览器以及不同的HTTP版本下,HTTP连接机制也不一样,比如HTTP 1.0 下,每次传输完一个文件后,这个HTTP请求(TCP)连接将关闭,需要重新发起(TCP三次握手)建立连接才能继续请求下一个文件,如果网络单程通信需要30ms建立一个连接需要90秒,关闭TCP还需要四次握手,同一个网站有90个文件需要重复这个步骤,那总共需要多少时间?可以看出这个严重影响了整个网页的加载速度。
低版本的浏览器IE 6, IE 7 甚至一次性只能发起2个连接,在发起HTTP请求到TCP请求之前,浏览器还需要发起一个前置的DNS域名解析查询请求,完成后才能发起HTTP请求。如果网站采用了HTTPS协议,上面的3次握手才能建立的连接请求将需要多增加4次握手确认才能开始通信。
距离对性能的影响
世界上最快的速度就是光速,光缆传输的速度首先肯定不会超过光速,光在光缆中通过光纤传输肯定会有损耗,最后在这个传输的过程中传输介质不仅仅是光纤,还包括了骨干网到ISP(电信运营商)、到用户家的普通网线、铜线、路由器、交换机等都有不同程度上的损耗。简单的举个例子:
光的速度是每秒可以达到299792458米(30万公里),对于一般的光纤来说,大部分从1.4~1.6不等,这个值越大,光在该介质中的传播速度就越慢。
哈尔滨到拉萨两地直线距离大概4100公里,假设数据通过光纤的速度为每秒200000000,取的折射率(损耗)是是1.5。两地之间纯光纤传输单程需要 21ms(毫秒),从光纤接入ISP(电信运营商)再到家又会损耗 9ms(毫秒),21 + (9 * 2) = 39 ms,单程传输理论上就需要 39 毫秒,如果3次握手乘以 3 就是需要 156 ms 毫秒,也就是两地用户之间在进行正式数据传输之前就需要156 毫秒了。
如果单个包超过了TCP最大能传输的单元(MTU)大小(1460字节)还可能会拆成多个来传输,据统计一个网站平均有90个文件请求(网页、图片、css、js 等),那最终用户请求获取完一个网页需要多少时间?
如何优化
TCP优化
服务器系统
在着手优化之前,首先要做的就是把服务器的操作系统升级到最新版本。TCP的最佳实践以及影响及其性能一直在与时俱进,而大多数优化都只在最新的内核中才实现。有可能你的服务器系统选型很早就已经确定了,也可能因为运维人员的个人喜好,不管出于什么原因以至于古老的系统因为各种原因一直沿用至今,但是实事求是的讲,让你的服务器跟的上这个时代是所有优化的首要措施(不仅仅只是硬件层面)。
服务器配置调优
增大TCP的初始拥塞窗口:可以让第一次往返就传输较多数据,而随后的提速也会很明显。
慢启动重启:禁用慢启动重启可以保证连接在闲置时重新传输数据可以仍然保持瞬间发送大量数据的能力。
窗口缩放:启用窗口缩放可以增大最大接收窗口的大小,可以让高延迟的连接达到更高的吞吐量。
TCP快速打开(Fast Open):如果你可以控制服务端可以客户端,可以尝试这个选项,它可以让TCP在第一个SYN分组中就传输数据。
以上几个建议可以再加上最新的服务器内核,可以确保TCP的最佳性能(每个TCP连接都具有较低的延迟和较高的吞吐量),这个影响不仅仅是用户请求网页,包括你服务器架构中众多的服务,负载均衡、分布式、集群、访问数据库、队列等等所有需要网络通信的应用性能和效率,具体的参数配置及设置由于篇幅请自行百度。
客户端优化
重用TCP连接至关重要,频繁的三次握手是对性能极大的浪费
不能让数据传输的更快,可以让数据传输的更短
压缩数据,减少不必要的比特传输
再快也快不不过什么也不用发,能少发就少发
消除不必要的连接和数据传输本身就是很大的优化,优化好TCP是所有应用高性能的前提和基础。
HTTP优化
幸运的是现代的浏览器越来越高效智能(相对IE时代),浏览器本身已经做了很多优化,单个域名下进行同时连接请求的并发数已经拓展到4~6个,同时如果觉的不够还可以设置多个域名;而且浏览器还会根据你的地址栏输入、访问记录,访问意向,鼠标悬停等方式对你要访问的网页进行预先DNS解析,预先建立连接,分优先级加载(优先加载网页、css、js)等方式对整体的访问速度和访问体验进行了优化,速度较比之前已经有了很大程度的提升,这也是为什么Chrome可以做到比IE快那么的原因。
浏览器
减少DNS查找:每一次主机名解析都需要一次网络往返,从而增加请求的延迟时间,同时还会阻塞后续请求。
重用TCP连接:尽可能使用持久连接,以消除 TCP 握手和慢启动延迟(Keep-Alive
减少HTTP重定向:HTTP 重定向极费时间,特别是不同域名之间的重定向,更加费时;这里面既有额外的 DNS 查询、 * TCP握手,还有其他延迟。最佳的重定向次数为零。
HTTPS优化:启用TLS的会话缓存和无状态恢复及共享(可以减少HTTPS后续验证时间)
去掉不必要的资源:任何请求都不如没有请求快。
在客户端缓存资源:应该缓存应用资源,从而避免每次请求都发送相同的内容。浏览器提供了 Cache-Control,Last-Modified 和 ETag 首部提供验证机制,可以让不经常变更的内容直接从本地获取避免重复访问服务器拉取同样的资源,要说最快的网络请求,那就是不用发送请求就能获取资源。
传输压缩过的内容:传输前应该压缩应用资源,把要传输的字节减至最少:确保对每种要传输的资源采用最好的压缩手段。 图片一般会占到一个网页需要传输的总字节数的一半,HTML、 CSS 和 JavaScript 等文本资源的大小经过 gzip 压缩平均可以减少 60%~80。
打包资源减少HTTP请求:拼接资源如图片精灵技术,合并CSS,JS等文件以减少HTTP请求。
合理设置资源域名:HTTP 规定为了防止客户端同时发起的请求过多给服务器造成自我DDOS,客户端对于单个域名一次最多不可发起超过6个并行请求,因此页面中同域名下资源太多,会造成等待6个资源的返而以防造成请求阻塞,可以用多个域名来突破并行请求数量。
距离优化
应用服务器
如果有条件,我们可以把应用服务器尽量部署到靠近用户的位置,没办法改变最大传输速度,可以缩短了两地之间的距离,自然也就缩短所需花费的时间。
CDN(Content Delivery Network)
对于静态资源(不需要经常改变的资源,如图片、文件、网页模板等)我们可以把它放到CDN上,让用户可以以最短的距离访问我们资源的路劲最短。
代理服务器
如果核心服务器没法部署到靠近用户近的地方,可以尝试用代理服务器,用户连接较近的服务器,由代理服务器通过专线、或者保持长连接的形式进行最终的服务访问。
最远的距离
如果机房连的是某个运营商的网络,用户是另一个运营商的网络,那么最终这中间也将造成极大的访问延迟,有条件机房应该部署的双线,否则可能会造成“世界上最远的距离不是天涯海角,而是你在电信,我在网通”。
Apple 曾经在 WWDC 上分享了一个对网络连接优化的取得巨大成功的案例,苹果工程师通过使用HTTP的持久连接和管道、重用iTunes中既有的连接,使得低网速用户的性能提升了原来的3倍。很明显,理解并且优化好网络层回报是巨大的。
浏览器
一个网页的加载速度不仅仅取决于资源的获取,就算资源已经达到用户的浏览器,达到完全解析并且并加载完成还需要布局和渲染和相关脚本的执行,因此最后部分是否也能保持高性能对用户的整体体验来说依然至关重要。用户对于性能的感知调查数据:
这个表格解释了Web性能社区总结的经验:必须在250ms内渲染页面,或者至少提供视觉反馈(告知、loading、进度条等),才能保证用户不走开。
从以上数据可以看出不管你的服务器实际运行的多快,如果想让用户感觉很快,就必须在几百毫秒内相应用户操作。超过1s,用户的预期流程就会中断,心思就会向其他任务转移,有数据表明7秒是用户可以忍受的平均极限,如果7秒没有响应大部分都会离开,10秒以上除非你有明确的反馈,否则用户基本上都会终止掉任务。一般说 Web 前端通常指的是网站业务逻辑之前的部分,影响前端的影响主要分为三部分。
取得资源
上一部分的内容其实已经包含了大部分浏览器获取内容大部分知识,这张我们谈一个也被人们忽视的新技术。
新协议
HTTP 协议简单的本质让它得以突飞猛进的发展,它的应用现在已经不仅仅在于Web浏览器方面,很多嵌入式设备如传感器、智能设备,设置咖啡壶都在用HTTP作为主要的控制和数据交换协议。但是由于原本的特性如纯文本协议传输、请求到响应的简单模式等已经无法满足于现代的近似实时响应速度的要求,为了应对这些挑战,2012年HTTP2.0的开发被提上日程,它原本是Google内部一个实验性的项目,因其极大的提升了Web的性能,因此被W3C作为 2.0 的基础,现已得到Chrome,Opera,Firefox等的支持,最大的改进:
多路复用
采用了数据格式化数据(头部和内容进行分离和压缩)
利用二进制数据分帧来传输数据(请求和响应)
可以设置请求优先级
服务器主动推送
并且支持向下兼容
技术成熟度
HTTP 2.0标准于2015年5月以RFC 7540正式发布,Google Chrome、Mozilla Firefox、Microsoft Edge和Opera已支持HTTP 2.0,并默认启用。Internet Explorer自IE 11开始支持HTTP 2.0,目前谷歌、Facebook、Twitter 等服务器已经采用2.0协议。
2016年4月26日 nginx-1.10.0 stable 也已经提供了对 HTTP 2.0的支持,理论上不需要对程序进行优化,仅仅更换 HTTP 2.0,就可以有效的提升50%以上的性能。
页面布局和渲染
随着互联网过去几十年的发展过程中,仅仅从超文本这个角度来看理解Web内容,已经不适用了,随着富媒体以及最近几年的H5的盛行,Web越来越像是是个应用程序,而不能单纯看成是个网页,但是影响浏览器最终加载完成呈现给用户的因素大体上可以分为以下几部分:
DOM:页面的内容最终在浏览器里解析后以DOM(Document Object Model)的形式来承载,也就是页面的实际内容,包括的了页面结构、文字、富媒体等。
CSSOM:页面的的表现形式CSSOM(CSS Object Model)的形式承载,也就是所谓的样式数据,关于数据应该怎么显示。
渲染树:随着DOM(页面有哪些内容)和CSSOM(页面应该怎样呈现)全部解析完成以后,浏览器将会基于二者创建渲染树,之后浏览器就有足够的数据去布局、绘制呈现内容给用户。
执行(Javascript)
在现代浏览器中JS是必不可少的,它决定了页面的业务逻辑、交互以及行为。但是在业务呈现完成之前,它却是个很大的祸害,脚本在解析执行的过程中,只要遇到同步的document.write将会阻塞DOM的解析和构建,同样,JS也会查询任何对象的计算样式、从而也成功的阻塞了CSS的处理,结果,DOM以及CSSOM的构建将频繁的交织在一起,DOM构建在JS执行完毕之前无法进行,而JS在CSSOM构建完成前也无法进行,因此如果不能处理好JS,将会严重的影响到页面的性能。
前端高性能
我们无法控制客户端与服务器之间的网络环境,也不能控制客户端的软硬件和其手持设备的配置,但除此之外一切还是掌握在我们的掌控之中的。
(1)跟上这个时代
之前很多方法都是为了解决浏览器和HTTP协议自身的缺陷和限制而做的变通方法,但幸福的是你现在你可以不用这么做了。HTTP 2.0 通过发明了新的交通工具汽车,让原来让人头疼的马粪的问题不用再去解决了。 以上的大部分问题在 HTTP 2.0 都已经有的新的实现机制,你现在唯一要做的就是时候勇敢的跟上时代,HTTP 2.0 完全向下兼容理论上你完全不需求更改你的应用程序就在之上运行。
(2)利用好现代浏览器提供的选项
dns-prefetch(预解析域名)
subresource(优先下载)
prefetch(预缓存将来要用的资源)
prerender(预渲染将来要访问的特定页面)
具体用法自行搜索。
(3)合理的规划资源请求的优先级
CSS 和 JavaScript 等重要资源应该尽早在文档中出现;
应该尽早交付 CSS,从而解除渲染阻塞并让 JavaScript 执行;
非关键性 JavaScript 应该推迟(放置在页面底部),以避免阻塞 DOM 和 CSSOM 构建;
(4)执行优化(Javascript)
避免全局变量
代码逻辑分层
便于多人协作开发
各部分代码模块化,可以按需加载
保持全局变量的清洁
可进行单元测试
(5)表现与业务逻辑解耦 如果实在无法让某些操作快速响应,至少让它看起来很快(提供视觉反馈)
后端服务架构
高性能架构肯定不仅仅指的是响应速度,还包括了能处理高的并发量,有高的吞吐量,一个好的高性能架构设计少不了理论的支撑,也少不了具体的套路,本部分将从两个方面展开。
理论
在解决高并发、海量数据处理、高可靠性等一系列问题和挑战的过程中,大型的互联网公司有很多被验证行之有效的解决方案,这些解决方案被更多的网站重复验证,形成了一套可靠的理论指导,在正确的理论基础上去打造高性能架构可以避免少走很多弯路。
(1)缓存
缓存就是将数据存放在距离计算最近的位置以加快处理速度。缓存是改善软件性能的第一手段,现代CPU越来越快的一个重要因素就是使用了更多的缓存,在复杂的软件设计中,缓存几乎无处不在。不管是在系统、软件还是网络在遇到性能瓶颈的时候通常缓存是非常有效的解决方案。
(2)异步
异步对应的是同步处理,简单的说异步就是发起计算任务后不需要也不能调用者立刻得到结果,处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。 如果是你要进行的操作非常耗时,一般我们选择先返回通知用户,复杂的业务逻辑在后台继续执行,不需用户等待。列如用户注册后可能涉及到开通账号、发送短信或者邮件、开通相关空间或者权限,实际上发短信或者发邮件等可能比较耗时操作也可能会引发失败,我们可以注册账号步骤完成后直接通知用户,后续的一系列操作后台通过队列等方式异步去执行,失败可以后台自动重试,用户已经可以利用账号和密码登陆。使用异步能有效的提高网站响应速度、提高系统可用性、提升整体的用户体验。
(3)分层(水平划分)
分层架构是将系统分成若干个水平层,每一层都有清晰的角色和分工,不需要知道其他层的细节,下层对上层屏蔽掉复杂的逻辑细节,层与层之间通过简单接口的通信,只要提供的接口不变,各层可以根据自己的需要进行各种升级改造而不影响其他层。分层架构是最常见的软件架构,也是事实上的标准架构。如果你不知道要用什么架构,那就用它。 虽然没有明确约定,软件一定要分成多少层,但是四层的结构最常见。
表现层(presentation):用户界面,负责视觉和用户互动
业务层(business):实现业务逻辑
持久层(persistence):提供数据,SQL 语句就放在这一层
数据库(database) :保存数据
通过分层对业务的横向切割,可以更好的将一个庞大复杂的软件系统划分层不同的部分,同时也便于合作开发和维护。分层还有一个特点,依赖关系都是从上往下,上层的服务依赖下层,下层的服务不会依赖上层,让依赖关系更加简单。典型经典的案列就是互联网的基础体系结构OSI参考模型。
(4)分割(垂直划分)
网站越大,功能越复杂,服务和数据处理的种类也越多,将这些不同的功能和服务分割开来,包装成高内聚低耦合的模块单元。一方面有助于软件的开发和维护,另一方面,便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力 大型Web应用程序分割的粒度可能会很小。比如在应用层,将不同业务进行分割,例如将购物、论坛、搜索、广告分割成不同的应用,由独立的团队负责,部署在不同的服务器上;在同一个应用内部,如果规模庞大业务复杂,会继续进行分割,比如购物业务,可以进一步分割成机票酒店业务、3C业务,小商品业务等更细小的粒度。而即使在这个粒度上,还是可以继续分割成首页、搜索列表、商品详情等模块,这些模块不管在逻辑上还是物理部署上,都可以是独立的。同样在服务层也可以根据需要将服务分割成合适的模块。
(5)分布式
百科的定义是“分布式处理则是将不同地点的,或具有不同功能的,或拥有不同数据的多台计算机通过通信网络连接起来,在控制系统的统一管理控制下,协调地完成大规模信息处理任务的计算机系统。”
简单的说分布式就是将不同模块部署在不同的服务器上,通过远程调用协同工作。分层和分割的一个主要目的是为了切分后的模块便于分布式部署。分布式意味着可以使用更多的计算机完成同样的功能,计算机越多,CPU、内存、存储资源也就越多,能够处理的并发访问和数据量就越大,进而能够为更多的用户提供服务。
但分布式在解决网站高并发问题的同时也带来了其他问题。首先,分布式意味着服务调用必须通过网络,这可能会对性能造成比较严重的影响;其次,服务器越多,服务器宕机的概率也就越大,一台服务器宕机造成的服务不可用可能会导致很多应用不可访问,使网站可用性降低;另外,数据在分布式的环境中保持数据一致性也非常困难,分布式事务也难以保证,这对网站业务正确性和业务流程有可能造成很大影响;分布式还导致网站依赖错综复杂,开发管理维护困难。因此分布式设计要根据具体情况量力而行,切莫为了分布式而分布式。
(6)集群
分布式是将不同的功能模块部署到多台计算机上,而集群简单的说是指将部署着同样功能组件的计算机集中起来提供服务。 因为服务器集群有更多服务器提供相同服务,因此可以提供更好的并发特性,当有更多用户访问的时候,只需要向集群中加入新的机器即可。同时因为一个应用由多台服务器提供,当某台服务器发生故障时,负载均衡设备或者系统的失效转移机制会将请求转发到集群中其他服务器上,使服务器故障不影响用户使用。所以在网站应用中,即使是访问量很小的分布式应用和服务,也至少要部署两台服务器构成一个小的集群,目的就是提高系统的可用性。
(7)冗余
网站需要7 24小时连续运行,但是服务器随时可能出现故障,特别是服务器规模比较大时,出现某台服务器宕机是必然事件。要想保证在服务器宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份,这样当某台服务器宕机时,可以将其上的服务和数据访问转移到其他机器上。
(8)自动化
在无人值守的情况下网站可以正常运行,一切都可以自动化是网站的理想状态。目前大型网站的自动化架构设计主要集中在发布运维方面。
网站在运行过程中可能会遇到各种问题:服务器宕机、程序Bug、存储空间不足、突然爆发的访问高峰。网站需要对线上生产环境进行自动化监控,对服务器进行心跳检测,并监控其各项性能指标和应用程序的关键数据指标。如果发现异常、超出预设的阈值,就进行自动化报警,向相关人员发送报警信息,警告故障可能会发生。在检测到故障发生后,系统会进行自动化失效转移,将失效的服务器从集群中隔离出去,不再处理系统中的应用请求。待故障消除后,系统进行自动化失效恢复,重新启动服务,同步数据保证数据的一致性。在网站遇到访问高峰,超出网站最大处理能力时,为了保证整个网站的安全可用,还会进行自动化降级,通过拒绝部分请求及关闭部分不重要的服务将系统负载降至一个安全的水平,必要时,还需要自动化分配资源,将空闲资源分配给重要的服务,扩大其部署规模。通过减少人为干预,使自动化可有效减少故障。
实践
正确使用架构方案可以更好地利用业界和前人的思想与实践,用更少的时间开发出更好的系统,使设计者的水平也达到更高的境界,使用者应该对自己的遇到的问题深刻分析后,再采取相应的解决方案,不恰当地使用模式只会画虎不成反类犬,不但没有解决原来的老问题,反而带来了更棘手的新问题,好的架构设计需要建立在对问题深刻理解之上的创造与创新。
应用服务器性能优化
应用服务器是处理网站业务的服务器,网站的业务代码都部署在这里,是网站开发最复杂,变化最多的地方,对于性能问题优化手段主要有缓存、集群、异步等。
(1)缓存
网站性能优化第一定律:优先考虑使用缓存优化性能。当网站遇到性能瓶颈时,第一个想到的解决方案就是使用缓存。在整个网站应用中,缓存几乎无所不在,既存在于浏览器,也存在于应用服务器和数据库服务器;既可以对数据缓存,也可以对文件缓存,还可以对页面片段缓存。合理使用缓存,对网站性能优化意义重大。
(2)异步
使用消息队列将调用异步化,可改善网站系统的性能。事实上,使用消息队列还可以让系统耦合性更低同时更加具有扩展性,在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发的情况下,会对数据库造成巨大的压力,同时也使得响应延迟加剧。在使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程(通常情况下,该进程通常独立部署在专门的服务器集群上)从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度远快于数据库(消息队列服务器也比数据库具有更好的伸缩性),因此用户的响应延迟可得到有效改善。消息队列具有很好的削峰作用即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。在电子商务网站促销活动中,合理使用消息队列,可有效抵御促销活动刚开始大量涌入的订单对系统造成的冲击。
(3)集群
在网站高并发访问的场景下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。
存储性能优化
在Web应用中,除了大量的业务逻辑需要CPU处理以外,另一个很大的性能问题是海量的数据读写对磁盘访问造成巨大压力,虽然可以通过Cache解决一部分数据读压力,但是很多时候,磁盘仍然是系统最严重的瓶颈。而且磁盘中存储的数据是网站最重要的资产,磁盘的可用性和容错性也至关重要。
(1)机械硬盘/固态硬盘
机械硬盘是目前最常用的一种硬盘,通过马达驱动磁头臂,带动磁头到指定的磁盘位置访问数据,由于每次访问数据都需要移动磁头臂,因此机械硬盘在数据连续访问(要访问的数据存储在连续的磁盘空间上)和随机访问(要访问的数据存储在不连续的磁盘空间)时,由于移动磁头臂的次数相差巨大,性能表现差别也非常大。在网站应用中,大部分应用访问数据都是随机的,这种情况下SSD具有更好的性能表现。固态硬盘又称作SSD或Flash硬盘,这种硬盘没有机械装置,数据存储在可持久记忆的硅晶体上,因此可以像内存一样快速随机访问。而且SSD具有更小的功耗和更少的磁盘震动与噪声,如果你的业务对磁盘读写速度有很高的要求可以尝试换SSD盘。
(2)RAID/HDFS
通常在服务器中我们经常使用 RAID(廉价磁盘冗余阵列)技术主要是为了改善磁盘的访问延迟,增强磁盘的可用性和容错能力。目前服务器级别的计算机都支持插入多块磁盘(8块或者更多),通过使用RAID技术,实现数据在多块磁盘上的并发读写和数据备份。RAID技术可以通过硬件实现,比如专用的RAID卡或者主板直接支持,也可以通过软件实现。RAID技术在传统关系数据库及文件系统中应用比较广泛,但是在大型网站比较喜欢使用的NoSQL,以及分布式文件系统中,RAID技术却遭到冷落。例如在HDFS中,系统在整个存储集群的多台服务器上进行数据并发读写和备份,可以看作在服务器集群规模上实现了类似RAID的功能,因此不需要磁盘RAID。HDFS 是一个高度容错性的文件系统,适合部署在廉价的机器上,HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。
结论
第一部分我们从对整个系统性能影响重大的因素网络,用户访问Web服务离不开网络,我们把内容传递到用户设备上也离不开网络,服务器之间内部通信更是完全依赖网络,因此网络的性能直接关系到整个产品的性能,而在现实中我们经常低估了它的重要性,TCP等传输协议和网络传输的距离和介质是对网络性能的最主要的影响因素。第二部分我们讨论了对用户感知最为明显的浏览器部分,用户的浏览器何时获取完内容,渲染和部署内容、以及最后的执行都会用户最终能感受到的性能息息相关。最后讨论了打造高性能架构的基石后端服务架构,可以看出来打造高性能Web应用有赖于大量的技术的,我们的产品的整体性能是所有这些组成部分性能的表现之和。
网站性能对最终用户而言是一种主观感受,性能优化的最终目的就是改善用户的体验,使他们感觉网站很快。离开这个目的,追求技术上的所谓高性能,是舍本逐末,没有多大意义。而用户体验的快或是慢,可以通过技术手段改善,也可以通过优化交互体验改善。
即使在技术层面,性能优化也需要全面考虑,综合权衡:性能提升一倍,但服务器数量也需要增加一倍;或者响应时间缩短,同时数据一致性也下降,这样的优化是否可以接受?这类问题的答案不是技术团队能回答的。归根结底,技术是为业务服务的,技术选型和架构决策依赖业务规划乃至企业战略规划,离开业务发展的支撑和驱动,技术走不远,甚至还会迷路。 当然也没有任何一个网站从出生第一天具备了超级高的访问量,网站的性能问题都是在成长的过程的逐步暴露出来的,不同的阶段会面临对应的问题,分析自己的产品和业务特征、现在具体面临的问题、因将来需要面临的挑战,然后应用合理方式去设计架构,正确使用理论可以更好地利用业界和前人的思想与实践,用更少的时间开发出更好的系统,使设计者的水平也达到更高的境界。但是每种理论模式受其适用场景限制,对系统的要求和约束也很多,不恰当地使用模式只会画虎不成反类犬,不但没有解决原来的老问题,反而带来了更棘手的新问题,好的架构设计绝对不是模仿,不是生搬硬套某个模式,一定是对问题深刻理解之上的创造与创新。
由于本文主题是高性能的Web架构,着重于从如何打造快速响应、应对高并发、高吞吐、让用户感受到非常快的体验的角度来进行阐述的,实际上,对于一个好的 Web 架构来说,除了高性能这个指标外,还必须兼顾高可用、可伸缩、可拓展、安全等多个方面,由于主题以及篇幅有限,虽文中也有提及但不展开详谈,读者有兴趣可以自行研究,期望本文的介绍能给对设计高性能架构感兴趣的同行学者提供一定的参考。
参考文献:
http://www.oreilly.com/programming/free/software-architecture-patterns.csp http://blog.sina.com.cn/s/blog_736c25910101g1c1.html http://www.cnblogs.com/developersupport/p/webpage-performance-best-practices.html