高性能网站建设指南

书籍:《高性能网站建设指南》【美】Steve souders 著 刘彦博 译  文章类型:学习笔记


网站优化方向:

前端优化:HTML、javascript、css、ajax、

后端优化:编译器选项、数据库索引、内存管理


性能的黄金准则:

1 如果我们可以将后端的响应时间缩减为一般,整体响应时间只能减少5%~10%,而如果关注前端性能,同样是将其响应时间减少一半,则整体响应时间可以减少40%~45%。 

2 只有10%~20%的最终用户响应时间花在了下载HTML文档上。其余的80%~90%时间花在了下载页面中的所有组件上。


B/S 架构下:客户端访问网站的过程:

浏览器端:用户:首次输入网站网址URL

                  浏览器:向特定URL发送HTTP请求

DNS服务器:域名解析,将特定的URL解析成匹配的IP地址

服务器:发回HTTP响应,Http响应包含状态码、头和响应体,同时响应文本中expires头明确指出浏览器是否可以使用组件的缓存副本来消除浏览器和服务器之间进行对页面是否更新检查的需要。

浏览器和服务器之间通过TCP建立持久连接.

浏览器:浏览器会解析HTML请求并开始下载页面中的组件。如果浏览器的缓存是空的,需要下载所有的组件HTML文档只占总响应时间的5%。用户需要花费其余95%的时间中的大部分时间来等待组件的下载,小部分时间在解析HTML、脚本和样式表。当浏览器看到响应中有一个expire头时,就会和相应的过期时间组件一起保存到缓存中。只要组件没有过期,浏览器就会使用缓存版本而不会进行http请求。

 

浏览器端:用户:在网站上跳转

                    浏览器:检查浏览器的缓存,查看是否已经存在缓存,如果缓存中的组件没有明确说明是否有效,浏览器就会向特定URL发送条件get请求

服务器:根据条件get请求,查看组件,返回组件的last-modified。


浏览器向服务器发送的请求类型:GET、POST、HEAD、PUT、delete、options、trace


优化前端的规则:

规则1:减少HTTP 请求

             只有10~20%的最终用户响应时间花在接收请求的html文档上。剩下的80~90%的时间花在html文档所引用的所有组件(图片、脚本、样式表、flash等)进行的http请求上。因此,改善响应时间的最简单途径就是减少组件的数量,并由此减少HTTP请求的数量。


方法1:使用图片地图既能减少HTTP请求,又无需改变页面外观感受

实现效果:

未使用图片地图:

使用图片地图:


使用图片地图的缺陷:在定义图片地图上的区域坐标复杂


方法2:使用css sprites ,将多个图片合并到一个单独的图片中

方法3:内联图片

1内联为立即数    data:URL 模式,允许将小块数据内联为‘立即数’,数据就在其URL自身之中。但由于data:url是内联在页面中的,在跨越不同页面是不会被缓存。

2 内联在样式表   将内联图片放置在外部样式表增加了一个额外的HTTP请求,但被缓存后可以得到额外的收获。

内联在样式表的优点:

单独的文件合并到一个文件中,可以减少http请求的数量并缩短最终用户响应时间。将多个脚本合并为一个脚本,多个样式表合并为一个样式表。理想情况下,一个页面应该使用不多于一个的脚本和样式表。

页面大小和响应时间有着很强的正比关系。

减少组件的数量是最重要的一部,用文本替换图片会给该页面带来性能的最大改进。


规则2:使用内容发布网络,在多个地理位置不同的服务器上部署内容

              如果应用程序web服务器离用户更近,则一个http请求的响应时间将缩短。如果组件web服务器离用户更近,则多个http请求的响应时间将缩短。

内容发布网络CDN是一组分布在多个不同地理位置的web服务器,用于更加有效第向用户发布内容。在优化性能时,向特定用户发布内容的服务器的选择基于对网络可用度的测量。推荐使用CDN服务提供商。

              有些需要最终用户使用一个代理来配置他们的浏览器,有的需要开发者使用不同的域名;修改他们组件的url。无论如何也不要使用http重定向来将用户指向本地服务器,这会使得web页面响应速度慢。

                 cdn 不仅缩短用户响应时间,还提供备份,扩展存储能力和进行缓存。


使用CDN注意问题:

             1 响应时间会受到其他网站影响,无法直接控制组件服务器,需要服务器提供商协助。

             2 建议使用多家CDN服务器提供商。

             3 CDN用于发布静态内容,如图片、脚本、样式表和flash。提供动态html页面会引入特殊的存储需求---数据库连接,状态管理、验证、硬件和os优化,超出CDN的能力范围。

              4 使用内容发布网络,CDN服务器的地理位置与用户的地理位置影响性能很大。

规则3:为组件添加长久的expires 头

              通过使用一个长久的expires头,使得图片、脚本和样式表可以被缓存,这会在后续的页面浏览中避免不必要的HTTP请求。

             expires 头可以用于图片、脚本、样式表和flash等组件。

              web服务器使用expires 头来告诉web客户端它可以使用一个组件的当前副本,直到指定的时间为止。


浏览器利用缓存的方式:

   1expires头使用一个特定的时间,它要求服务器和客户端的时钟严格同步,而且时间一旦落后,就需要立马更新。

   

  2 cache-control使用max-age 指令指定组件被缓存多久

 使用浏览器缓存注意的问题:

               组件在浏览器中缓存,会减少响应时间,但已经访问过网站的用户也不大可能获取最新的组件,因为前一个版本已经在浏览器中缓存了。为了确保用户能获取用户的最新版本,最有效的解决方案是修改其所有链接。这样,全新的请求可以将从原始服务器下载最新的内容,修改文件名即可更新。


规则4:压缩组件

                  通过减少HTTP响应的大小来减少响应时间。如果HTTP请求产生的响应包很小,传输时间就会减少。使用gzip编码来压缩HTTP响应包,并由此减少网络响应时间。还可以删除注释和缩短URL。  

                  可以压缩HTML文档,脚本和样式表,也可以压缩xml和json。图片和pdf不应该压缩,因为他们本来就已经被压缩了。

                 配置gzip时使用的模块取决于apache的版本。

                 gzip在apache上的配置详见:http://www.schroepl.net/projekte/mod_gzip

                  在web服务器的响应中添加vary头,web服务器可以告诉代理根据一个或多个请求头来改变缓存的响应。由于压缩的决定是基于accept-encoding请求头的,因此需要在服务器的vary响应头包含accept-encoding。当浏览器带着accept-encoding gzip访问代理时,接收到的死压缩过的内容,否则就不是压缩过的内容。

                代理的边缘情形:默认情况下,ETag不能放映出内容是否被压缩,因此代理可能会想浏览器提供错误的内容。

                对web服务器配置进行简单的修改,压缩尽可能多的组件,就能显著改善页面的反应速度。


规则5:使用link标签将样式表放在顶部

   HTML页面就是进度指示器,当浏览器逐步加载页面时,页头、导航栏,顶端logo等,所有这些都会等待页面的用户提供视觉反馈,有助于改善用户体验。

 

进度指示条的三个主要优势: 为用户提供可视化回馈很重要。

1 让用户知道系统没有奔溃

2指出用户大概需要多久,以便用户能够在漫长的等待中做些其他事情

3能够为用户提供一些可以看的东西,使得等待不再那么无聊


样式表存放位置分析:

           1 如果将样式表放在文档底部会导致浏览器阻止内容逐步呈现,这是因为浏览器在绘制页面元素时,会因为逐步读取底部的样式表而重新绘制页面,在页面没有固定时,浏览器会阻塞内容逐步呈现,直至页面样式稳定。

           2 如果将样式表放在文档顶部,浏览器会逐步呈现页面内容,对于实际绘制内容的时间没有影响,但会给用户较好的体验。

 

会导致白屏的情形:

1 在新窗口中打开

2 重新加载

3作为主页


 将样式表放在文档顶部的方式:


注意:一个style块可以包含多个@import规则,但@import规则必须放在其他规则之前。使用@import规则会导致组件下载时的无序性,会阻塞页面逐渐呈现。样式表在页面中的位置并不影响下载时间,但会影响页面的呈现。


规则6—将脚本放在底部

                   使用脚本时,对于所有位于脚本以下的内容,逐步呈现都被阻塞了。将脚本放在页面越靠下的地方,意味着越多的内容能够逐步地呈现。

                   Http1.1规范建议浏览器从每个主机名并行地下载两个组件。默认情况下,IR和Firefox都遵守这一建议。如果一个web页面平均地将其组件分别放在两个主机名下,整体响应时间可以减少大约一半。简单地使用DNS别名可以将组件分别放到多个主机名中。但增加并行下载数量并不是开销的,过多地下载反而会降低性能。

 

在下载脚本时并行下载实际上是被禁用的:

原因之一:脚本document.write 会修改页面内容,浏览器会等待,以确保页面能够恰当地布局

原因之二:如果并行下载多个脚本,无法保证响应应是按照特定顺序到达浏览器的。


 脚本对页面的影响:

1脚本会阻塞对其后面内容的呈现

2脚本会阻塞对其后面组件的下载

如果脚本使用document.write 向页面中插入了内容,就不能将其移动到页面中靠后的位置。

  使用延迟脚本,defer属性表明脚本不包含document.wirte,这样的脚本可以移到页面底部,不会影响页面呈现。


规则7—避免CSS表达式

  对css表达式频繁的求值使其得以工作,也导致CSS的表达式低下性能。

  CSS表达式不仅仅会在页面呈现和大小改变时求值,当页面滚动,甚至用户鼠标在页面上移过时都会进行求值。


 避免CSS表达式的方法:

1创建一次性表达式

2 使用事件处理器取代CSS表达式

使用事件处理器来为特定的事件提供所期望的动态行为,避免了浏览器在无关事件发生时对表达式多次求值。


规则8:使用外部javascript和CSS

  有时候,内联会比外部快,因为外部需要承担多个HTTP请求带来的开销。但是更多情况下,因为javascript和CSS文件有机会就会被浏览器缓存起来,包含动态内容的HTML文档,通常不会被配置为可以进行缓存的,每次请求这样的HTML文档都要下载内联的javascript和css,会导致页面呈现较慢。使用外部文件提供javascript和css带来的收益会随着每用户每月的页面查看次数或每用户每会话产生的页面查看次数的增长而增加。

 

主页倾向于使用内联,内联javascript和css 文件,页面加载速度更快,同时,一般网站主页在浏览器每次启动都会缓存,在浏览器结束时都会自动清空缓存。

 

对于多次页面查看中的第一次的主页,主页内联javascript和css,但又能为所有后续页面查看提供外部文件。这可以通过主页加载完成后动态下载外部组件来实现。这能够将外部文件放到浏览器的缓存中以便用户接下来访问其他页面。

javascript和css 被加载到页面中两次,先是内联,然后是外部,由于下载两次,会出现双重定义,解决方法是将组件放到IFram中

当用户第一次访问页面时,服务器发现没有cookie,于是生成一个内联组件的页面。然后服务器添加javascript来在页面加载后动态下载外部文件—javascript、css,并设置cookie,下一次访问页面时,服务器看到cookie,就睡生成一个使用外部文件的页面。


如果用户重新打开浏览器,基于会话的cookie会消失,但组件依然会存在缓存中。这会使得页面加载javascript和css 时出现,可以将cookie从基于会话的改为短期的(数小时或数天)。


规则9 :通过使用keep-alive和较少的域名来减少DNS查找

       输入URL,DNS服务器根据域名寻找指定的IP地址。在DNS查找匹配的IP地址完成之前,浏览器不能从主机名那里下载到任何东西。响应时间依赖于DNS解析器所承担的请求压力,用户与DNS解析器之间的距离和用户的带宽速度。

 

   DNS查找可以被缓存起来以提高性能,用户请求了一个主机名之后,DNS信息会留在操作系统的DNS缓存中,以后对于该主机名的请求将无需进行过多的DNS查找。

      查找返回的DNS记录包含了一个存活时间TTL,告诉客户端可以对记录缓存多久。

过短的TTL会使得DNS记录很快失效,过长的TTL值会使得服务器故障转移速度降低。

   微软操作系统的DNS缓存由DNS client服务进行管理。


IE浏览器和firefox浏览器都会进行dns 缓存。

IE浏览器的DNS缓存由三个注册表设置控制—DnsCacheTimeout、KeepAliveTimeout和ServerInfoTimeOut。

 

一个持久的TCP连接(Keep-alive)会一直使用,直到其空闲1分钟为止。由于连接是持久的,因此无需DNS查找,另外Keep-Alive通过重用现有连接避免了重复的DNS查找。

确保服务器支持keep-alive,以减少用户导航到网站时所需的DNS查找。

主机名数量包括页面URL、图片、脚本文件、样式表、flash对象等的主机名。减少唯一主机名的数量可以减少DNS查找的数量,但会潜在减少页面中并行下载的数量。由于每个主机名可以并行下载两个组件,使用一个主机名既减少DNS查找的数量,有最大化了并行下载。

规则10 : 对javascript源代码进行精简

  javascript是一门解释型语言,是构建web页面的首选。当以快速原型为基准开发用户界面时,解释语言要优于其他语言。

   从javascript代码中移除不必要的字符以减少其大小,进而改善加载时间。在代码被精简之后,所有的注释以及不必要的空白字符(空格、换行、制表符)都将被移除。

   混淆也会移除注释和空白,同时也会改写代码。作为改写的一部分,函数和变量的名字将被装换为更短的字符串,这时代码更加精炼,也难阅读。混淆是为了增加对代码进行反向工程的难度,但也提高了性能。

 

混淆的缺陷:

1 混淆过程本身很有可能引入错误

2 混淆会改变javascript符号,因此需要对任何不能改变的符号进行标记,防止混淆器修改它们。

3经过混淆的代码很难阅读,使得在产品环境中调试更加困难。


javascript的精简工具:

JSMin 和DoJoCompressor


精简css也能带来加载性能的优化,CSS的精简在于 移除注释和空白,合并相同的类,移除不使用的类,使用缩写(用#606 代替‘#660066’,移除不必要的字符串(用‘0’代替‘0px’)


规则11 :寻找一种避免重定向的方法

重定向 用于将用户从一个URL重新路由到另一个URL。

进行重定向的原因:网站重新设计、跟踪流量、记录广告点击、简历易于记忆的URL

当web服务器向浏览器发送HTTP响应头时,浏览器会自动将用户带到Location 字段所给出的URL。

HTML文档中的头包含的metarefresh标签可以在其content属性所自定的秒数之后重定向用户。

javascript也可以用于重定向,将document.location设置为期望的URL即可。

重定向会延迟整个HTML文档的传输,在HTML文档到达之前,页面中不会呈现出任何东西,也没有任何组件会被下载。

重定向最为浪费、发生得很频繁的是,URL的结尾必须出现斜线(/)而没有出现时。

例如:访问http://astrology.yahoo.com/astrology,允许自动索引,并且能够获得与当前目录相关的URL。这是因为浏览器在进行GET请求时必须指定一些路径,如果没有路径,就会简单地使用文档根(/),发生重定向。


规则12:  确保脚本只被包含一次

     重复脚本损伤性能的方式:1 不必要的HTTP请求 2执行javascript所浪费的时间

      在页面中多次包含相同的脚本会使页面变慢

在IE中,如果脚本没有被缓存,或在重新加载页面时,会产生额外的HTTP请求

在Firefox和IE中,脚本会被多次求值。

 

避免重复脚本的方法:

1在HTML 页面中使用SCRIPT 标签

      2在PHP创建insertScript函数



规则13 :配置或移除ETAG

     通过最大化浏览器缓存组件的能力,减少呈现页面时所必需的HTTP请求的数量能加速用户体验。

    实体标签是web服务器和浏览器用于确认缓存组件的有效性的一种机制。


浏览器: ----URL HTTP 请求  --DNS域名解析  ---服务器

浏览器   首次下载组件,存储到缓存中

浏览器再次访问组件,发送一个条件GET请求,服务器发来组件的Expires 头,浏览器检查 组件是否过期,没有过期,不产生HTTP请求,已经过期,产生HTTP请求

 

服务器在检测缓存的组件是否和原始服务器的组件匹配时,有两种方式

1 比较最新修改日期


2 比较实体标签


ETAG 的加入为验证实体提供了比最新修改日期更为灵活的机制。例如,如果实体依据user-agent 或accept-language 头而改变,实体的状态可以反映在Etag中。


Etag的缺陷:

     当浏览器从一台服务器上获取了原始组件,之后,又向另外一台不同服务器发起条件GET请求时,ETAG是不会匹配的、对于拥有多台服务器的网站,Apache和IIS向ETAG中嵌入的数据都会大大地降低有效性验证的成功率。

   如果在多台服务器上寄宿网站,而且使用的是具有默认Etag配置的Apache或IIS,用户将面对缓慢的页面,服务器会有很高的负载,消耗大量的带宽,代理不能有效地缓存缓存内容。


    Apache 可以从Etag中移除inode值,只留下大小和时间戳作为组件的Etag。IIS中可以为所有服务器设置相同的ChangeNumber,保留文件的时间戳作为ETag。这样会提高多台服务器同一个组件匹配Etag的成功率。

    从Etag中移除changeNumber或完全移除Etag可以避免当数据已经位于浏览器缓存中进行不必要的和低效的下载。


规则14:确保ajax请求遵守性能指导,尤其应具有长久的expires 头

ajax 是DHTML中使用的一项技术,客户端可以获取和显示用户请求的新信息而无需重新加载页面。

Ajax 层位于客户端,与web服务器进行交互以获取请求的信息,并与表现层交互,仅更新那些必要的组件。

  尽管ajax请求不是可缓存的,其他性能指导原则都可以运用,如压缩响应,缩短域名查找时间,精简脚本,不使用重定向,移除ETag。



总结:

         根据黄金性能准则,终端用户等响应时间更多花费在组件的解析以及下载上,如何减少组件的下载就成为优化网站性能的关键。

1减少HTTP请求数量:

    1.1是减少组件的HTTP请求,可以同多个组件绑定一个URL

    1. 2避免多次重定向,其本质也是下降HTTP请求  

2缩短HTTP的传输距离

     利用CDN优化

3精简HTTP的传输内容

       3.1 压缩组件

       3.2压缩javascript

      3.3压缩CSS

      3.4避免重复使用脚本

4延长HTTP的有效期(即使得组件有效期延长)

          4.1 expires 头延长组件有效期

          4.2配置或移除ETag 使得组件有效识别成功率提高

5改善用户体验

        5.1样式表放置在顶部

        5.2脚本放置在底部

6减少网站内容的运算时间

       6.1 减少CSS运算

       6.2 减少javascript进行复杂操作

7使得B与S之间的连接更快

       7.1使用较少域名,减少DNS查找

       7.2使用keep-alive,使得DNS有效期延长,减少DNS    



 





高性能网站建设指南 “如果实现了Steve这些建议中的20%,你的站点就能出现戏剧性的变化。有了这本书和YSlow扩展,实在是没有理由再构建出运行速度缓慢的网站了。”         ——Joe Hewitt,Firebu9调试器和Mozilla的DOM解释器的开发者   “Steve Souders完成了一项神奇的工作,他提出了一系列简明的、可操作的,并且注重实效的开发步骤,使Web性能世界发生了翻天覆地的改变。”         ——Eric Lawrence,微软Fiddler Web Debugger开发者   想让你的网站显示得更快?本书提供了14种规则,可以使用户在请求页面时减少20%~25%的响应时间。作为Chief Performance Yahoo!,作者Steve Souders收集了在优化网络时访问最多的页面积累下来的最佳实践。即使网站已经进行了高度的优化——如Yahoo!Search和Yahoo!首页——我们也能从这些出奇简单的性能规则中获益。   《高性能网站建设指南》一书介绍了如何针对网站中的Ajax、CSS、JavaScript、Flash和图片进行性能优化。每个性能规则都提供了示例,在本书的配套网站上可以找到代码片段。这些规则包括:   •减少HTTP请求     •使用外部JavaScript和CSS   •使用内容发布网络   •减少DNS查找   •添力Expires头     •精简JavaScript   •压缩组件       •避免重定向   •将样式表放在顶部 •移除重复脚本   •将脚本放在底部   •配置ETag   •避免CSS表达式   •使Ajax可缓存   如果你希望构建高流量页面,并且改善用户访问网站的体验,那么本书是你不可或缺之物。   Steve Souders,Chief Performance Yahoo!,为Yahoo!的其他产品团队开发了性能分析工具,并致力于推广这些最佳实践和工具。在加盟Yahoo!之前,Stevee曾就职于多家中小型公司,其中有两家还是他协办的——Helix Systems和CoolSync。他是斯坦福大学管理科学与工程硕士。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值