网站访问优化之-内容篇-减少DNS查找

减少DNS查找

域名系统(DNS)将主机名映射到IP地址,就像电话本将人名映射到他们的电话号码一样。当您在浏览器中键入www.yahoo.com时,浏览器联系的DNS解析器会返回该服务器的IP地址。DNS有成本。DNS通常需要20-120毫秒才能查找给定主机名的IP地址。直到DNS查找完成,浏览器才能从此主机名下载任何内容。

DNS查找缓存更好的性能。这种缓存可以在由用户的ISP或局域网维护的特殊缓存服务器上发生,但是在个人用户的计算机上也存在缓存。DNS信息保留在操作系统的DNS缓存(Microsoft Windows上的“DNS客户端服务”)中。大多数浏览器都有自己的缓存,与操作系统的缓存分开。只要浏览器在自己的缓存中保存了一条DNS记录,就不会因操作系统请求记录而烦恼。

按照DnsCacheTimeout注册表设置的指定,Internet Explorer默认缓存DNS查找30分钟 。Firefox缓存DNS查找1分钟,由network.dnsCacheExpiration配置设置控制。(Fasterfox将其更改为1小时。)

当客户端的DNS缓存为空(对于浏览器和操作系统)时,DNS查找的数量等于网页中唯一主机名的数量。这包括页面URL,图像,脚本文件,样式表,Flash对象等中使用的主机名。减少唯一主机名的数量可以减少DNS查找的次数。

减少唯一主机名的数量有可能减少页面中发生的并行下载量。避免DNS查找会缩短响应时间,但减少并行下载可能会增加响应时间。我的准则是将这些组件分成至少两个但不超过四个主机名。这在减少DNS查询和允许高度平行下载之间取得了很好的折衷。

缩小JavaScript和CSS

缩小是从代码中删除不必要的字符以减小其大小从而缩短加载时间的做法。代码缩小时,所有注释都将被删除,以及不需要的空白字符(空格,换行符和制表符)。在JavaScript的情况下,由于下载的文件的大小减小,所以这提高了响应时间性能。JSMin和YUI Compressor是用于缩小JavaScript代码的两个流行工具。YUI压缩机也可以缩小CSS。

混淆是可以应用于源代码的替代优化。它比缩小更复杂,因此更容易由于迷惑步骤本身而产生错误。在对美国十大网站的调查中,缩小比例达到了21%,而混淆度达到25%。尽管混淆的尺寸减小了很多,但缩小JavaScript的风险较小。

除了缩小外部脚本和样式之外,内嵌<script>和<style>块也可以并且应该被缩小。即使你用gzip脚本和样式,缩小它们的大小也会减少5%或更多。随着JavaScript和CSS的使用和大小的增加,通过缩小代码所节省的成本也会增加。

避免重定向

重定向是使用301和302状态码完成的。以下是301响应中HTTP标头的示例:

HTTP / 1.1 301永久移动
 位置:http://example.com/newuri
 内容类型:文本/ HTML

浏览器自动将用户带到在该Location字段中指定的URL 。重定向所需的所有信息都在标题中。响应的主体通常是空的。尽管他们的名字,301,也不是一个302响应在实践中被缓存,除非额外的头,如Expires或Cache-Control,表明它应该是。元刷新标记和JavaScript是将用户引导到其他URL的其他方法,但是如果您必须执行重定向,则首选技术是使用标准的3xx HTTP状态代码,主要是为了确保后退按钮正常工作。

要记住的主要是重定向减慢用户体验。在用户和HTML文档之间插入重定向会延迟页面中的所有内容,因为页面中没有任何内容可以呈现,并且在HTML文档到达之前不会开始下载任何组件。

最浪费的重定向之一经常发生,Web开发人员通常不知道。当一个URL中应该有一个尾部的斜杠(/)时,就会发生这种情况。例如,访问http://astrology.yahoo.com/astrology会得到一个301响应,其中包含http://astrology.yahoo.com/astrology/的重定向(注意添加的尾部斜线)。如果您使用的是Apache处理程序,则在Apache中通过使用Aliasor mod_rewrite或者DirectorySlash指令修复。

将旧网站连接到新网站是重定向的另一个常见用途。其他包括连接网站的不同部分,并根据一定的条件(浏览器类型,用户帐户类型等)指导用户。使用重定向连接两个网站很简单,只需要很少的附加代码。尽管在这些情况下使用重定向会降低开发人员的复杂性,但会降低用户体验。这种重定向的替代方案包括使用Alias和mod_rewrite如果两个代码路径托管在同一台服务器上。如果域名更改是使用重定向的原因,另一种方法是与Alias或组合创建一个CNAME(一个DNS记录,用于创建从一个域名指向另一个域名的别名)mod_rewrite。

删除重复的脚本

在一个页面中包含两次相同的JavaScript文件会使性能受损。这不像你想像的那么不寻常。对美国十大网站的回顾显示,其中两个包含重复的脚本。两个主要因素增加了在单个网页中复制脚本的几率:团队规模和脚本数量。当发生这种情况时,重复的脚本通过创建不必要的HTTP请求而损害了性能,并浪费了JavaScript执行。

不必要的HTTP请求发生在Internet Explorer中,但不在Firefox中。在Internet Explorer中,如果外部脚本包含两次并且不可缓存,则会在加载页面期间生成两个HTTP请求。即使脚本是可缓存的,当用户重新加载页面时,也会发生额外的HTTP请求。

除了产生浪费的HTTP请求之外,浪费时间多次评估脚本。无论脚本是否可缓存,这种冗余JavaScript执行都会在Firefox和Internet Explorer中发生。

避免意外包含同一个脚本两次的一种方法是在模板系统中实现一个脚本管理模块。包含脚本的典型方法是在HTML页面中使用SCRIPT标签。

<script type =“text / javascript”src =“menu_1.0.17.js”> </ script>

PHP中的一个替代方法是创建一个名为的函数insertScript。

<?php insertScript(“menu.js”)?>

除了防止多次插入相同的脚本之外,该函数还可以处理脚本的其他问题,例如依赖性检查和将版本号添加到脚本文件名以支持将来的Expires头文件。

配置ETags

实体标签(ETags)是Web服务器和浏览器用来确定浏览器缓存中的组件是否与源服务器上的组件匹配的机制。(“实体”是另一个词“组件”:图像,脚本,样式表等)ETag被添加来提供一种机制来验证比上一次修改日期更灵活的实体。ETag是唯一标识组件特定版本的字符串。唯一的格式约束是字符串被引用。源服务器使用ETag响应头指定组件的ETag 。

HTTP / 1.1 200 OK
 Last-Modified:Tue,2006年12月12日03:03:59 GMT
 ETag:“10c24bc-4ab-457e1c1f”
 内容长度:12195

之后,如果浏览器必须验证组件,则使用If-None-Match标头将ETag传递回原始服务器。如果ETag匹配,则返回一个304状态码,这个例子减少了12195字节的响应。

GET /i/yahoo.gif HTTP / 1.1
 主持人:us.yimg.com
 If-Modified-Since:星期二,2006年十二月12日03:03:59 GMT
 If-None-Match:“10c24bc-4ab-457e1c1f”
 HTTP / 1.1 304未修改

ETags的问题在于它们通常是使用属性来构建的,这些属性使得它们对于托管站点的特定服务器是唯一的。当浏览器从一台服务器获取原始组件时,ETag将不匹配,并且稍后尝试在另一台服务器上验证该组件,这种情况在使用服务器集群处理请求的网站上非常常见。默认情况下,Apache和IIS都将数据嵌入到ETag中,这大大降低了在具有多个服务器的网站上进行有效性测试的几率。

Apache 1.3和2.x的ETag格式是inode-size-timestamp。虽然给定的文件可能位于多个服务器的相同目录中,并且具有相同的文件大小,权限,时间戳等,但是其inode不同于一个服务器。

IIS 5.0和6.0与ETags有类似的问题。IIS上ETags的格式是Filetimestamp:ChangeNumber。A ChangeNumber是用于跟踪对IIS的配置更改的计数器。ChangeNumber网站后面的所有IIS服务器都不可能是相同的。

最终的结果是由Apache和IIS生成的ETags完全相同的组件不会从一台服务器到另一台服务器。如果ETag不匹配,用户不会收到ETags设计的小而快的304响应; 相反,他们会得到一个正常的200响应以及组件的所有数据。如果您只在一台服务器上托管您的网站,这不是一个问题。但是,如果您有多台托管您的网站的服务器,并且您使用的是默认的ETag配置的Apache或IIS,那么您的用户的页面速度会变慢,您的服务器负载也会增加,消耗的带宽也会越来越多,高效地缓存您的内容。即使你的组件有一个更远的Expires标题,每当用户点击刷新或刷新时,仍然会发出条件GET请求。

如果您没有充分利用ETags提供的灵活验证模型,最好只删除ETag。该Last-Modified头验证基于对组件的时间戳。删除ETag会减少响应和后续请求中的HTTP头的大小。此Microsoft支持文章介绍如何删除ETags。在Apache中,只需将以下行添加到Apache配置文件即可完成:

FileETag没有