缓存设计详解:低成本的高性能Web应用解决方案

译文
开发 前端
网站性能直接影响访问速度,从而影响访问量。实现高性能Web应用的重要性是不言而喻的。性能瓶颈主要体现在高延时、拥塞和服务器负载,专业的解决方法往往成本较高。做好缓存的设计则可以在控制成本的情况下充分的提高性能。

【51CTO精选译文】过去几年中,Web应用程序已经从简单的HTML页面堆积演变成使用各种各样的技术构建高可扩展性和交互式的富应用程序。设计和开发这类应用程序变得越来越复杂,此外,决策者正越来越多地寻求构建更丰富的互动功能到这些应用程序中,同时还要保证可维护性和高性能,但高性能意味着高成本。为了构建提供给最终用户体验的是一个牢固的应用程序,开发人员需要解决潜在的性能瓶颈。

本文侧重于缓存——它是交付高性能Web应用程序急需的——也简要介绍一下压缩功能。有一些公司在生产和销售专门的压缩和性能产品。本文旨在简单介绍在寻求专业产品解决性能问题之前开发人员可以在客户端和服务器端对Web应用程序做的一些性能改进。

性能瓶颈

性能瓶颈主要体现在高延时拥塞服务器负载。缓存不能完全解决掉这三个问题,但经过详细的设计考虑,缓存是可以提高性能的。在服务器端和客户端都缓存内容,据调查,平均而言,下载HTML只需要总的用户响应时间的10-20%,剩下的80-90%全部用于下载页面中的其它组成内容,这些组成内容通常包括图像,如公司logo,缓存logo可以有效避免到服务器的多次往返。在前日51CTO上发布的加速,加速,再加速:来自Google的网站加速技巧大全中,Google提到的提升网站速度和性能的低成本技巧中就包括缓存这一条。至于架构设计方面,则可参考51CTO的视频专题:大型网站架构专家谈

简单地讲,缓存是临时存储。它将数据复制到不同的计算机或不同于原始数据源的位置,有了正确的配置,访问缓存数据的速度比访问原始数据的速度要快得多,使用缓存数据可以减小服务器负载和带宽消耗,从最终用户的角度来看就是性能提高了。

图1显示了Internet如何工作的快速总揽,以及缓存在哪里发生作用。

图 1 Internet上的缓存:这个图显示了常见的请求和检索缓存信息的时机 
图 1 Internet上的缓存:这个图显示了常见的请求和检索缓存信息的时机

缓存

正如你在图1中所看到的,在服务器和客户端上缓存数据既是可能的也是有效的,图2显示了这三个缓存位置的不同视图。

图 2 缓存配置:此图显示了三个典型的缓存位置 
图 2 缓存配置:此图显示了三个典型的缓存位置

1、客户端浏览器缓存:浏览器缓存Web对象后,可以对重复的请求直接响应,不用再从Internet请求数据了。

2、服务器端转发代理缓存:虽然可能有些变化,但这些缓存位置通常是在最终用户防火墙里面,可以对请求直接响应,不需要从原始来源请求数据。

3、服务器端反向代理缓存:也被称为网关或代理缓存,这些缓存服务器的操作代表了客户的来源服务器,术语“内容分发网络(CDN)”就是这些反向代理缓存的集合。

你可以缓存任何可能不止一次被请求的对象,但总有一个危险就是缓存的对象很可能变得陈旧,也就是说,没有准确地反应原始数据。不过可以使用两个参数来控制所有可缓存的对象:freshness和validation。freshness和validation都可以使用HTTP请求和相应组合来进行确定。

◆Freshness确定某个对象是否可以从缓存中获得,使用expires和cache-control:max-age头进行控制。

◆Validation确定某个对象是否已经陈旧,使用last-modified和if-modified-since头进行控制。

设计高度缓存的Web应用程序

企业级Web应用程序既有静态部分又有动态部分,只要进行了正确的设计和架构,都能够实现静态部分从缓存中获取,动态部分从原始服务器获取,但第一步是确定要缓存什么,图3提供了一个指南,可以帮助你确定哪些对象是可缓存,哪些对象是动态的(不可缓存的)。

图 3 确定缓存能力:此图提供了某个对象是否应该缓存的指南 
图 3 确定缓存能力:此图提供了某个对象是否应该缓存的指南

应用程序架构在可缓存对象和不可缓存对象之间有一点差异,开发人员应该寻求最大限度的缓存命中率,同时要避免缓存动态对象。下面是一些最佳实践:

1、使用缓存控制(cache-control:max-age)和有效期(Expires)头

2、使用最后修改时间(last-modified)头

3、检查Web服务器是否支持If-Modified-Since

4、调查为小型站点使用转向代理的可行性,或为大型企业网站从CDN厂家获得专业人员的帮助

5、根据网站的可扩展性思考是使用数据中心还是托管

6、自己动手编码常常需要大量的时间和精力,根据站点的规模,可以考虑采用开源缓存方法,如使用Squid作为代理服务器

7、为文件下载明确使用混合缓存机制

8、确保那些无用户/输入依赖的动态事务可以获得缓存,为不同对象创建缓存映像可以帮助将可缓存对象和不可缓存对象隔离开来

9、小心完全忽略缓存头的内容管理系统(CMS)

#p#

为缓存使用头(Header)

本节覆盖了为缓存目的最有用的头。

控制缓存

在HTTP 1.1规范中,服务器应该为缓存控制头发送一个无缓存响应,以指出内容不应该被缓存,客户端和服务器端都应该遵守这个头信息,以防止头中已经声明了的动态内容,大多数开发语言都支持使用这个头信息控制响应头值。

另一方面,你可以为cache-control头返回一个public服务器端应答来允许缓存(即使没有cache-control头也可以指出对象是可以缓存的),cache-control头的值为private是一个特殊情况,表示浏览器可能会在本地缓存对象,但代理服务器不会缓存它。

图4中的请求——响应工作流显示了Google如何通过cache-control头通知代理服务器不要缓存的。

图 4 停止代理服务器缓存:请求--应答流显示服务器返回private阻止代理服务器缓存 
图 4 停止代理服务器缓存:请求--应答流显示服务器返回private阻止代理服务器缓存

最后,服务器使用expires应答时包括了一个表示有效期的日期/时间戳,直到有效期满之前浏览器都可以缓存中的对象。如图5所示。

图 5 过期内容:Google的Gmail服务器返回一个expires头,包括缓存页面的过期日期和时间 
图 5 过期内容:Google的Gmail服务器返回一个expires头,包括缓存页面的过期日期和时间

这一点你可以验证,Gmail允许浏览器缓存Gmail主页,直到expires头中明确指定的时间到了为止。

使用Last-Modified 头

浏览器使用这个头信息来确定缓存对象生存期的有效性,浏览器请求这个对象时,服务器使用一个包含该对象最后修改时间的时间戳的Last-Modified 头进行响应,当用户下次请求相同的对象时,如果当前的时间戳超出了对象的使用期限,或者用户是通过刷新方式请求该页面的,浏览器会向服务器发送一个if_modified_since请求确定对象是否发生了变化,如果对象的确发生了变化,浏览器就发送一个完整的GET请求以获取新的对象并将其再次缓存起来,否则,浏览器就从它的缓存中提取对象,并更新对象的last-modified值。图6显示了一个工作实例。

图 6 最后修改时间:last-modified时间戳让浏览器确定是使用本地缓存内容还是重新请求内容 
图 6 最后修改时间:last-modified时间戳让浏览器确定是使用本地缓存内容还是重新请求内容

举一个例子,假设浏览器在请求www.yahoo.com时,服务器使用last-modified时间戳进行响应,和使用if-modified-since头进行响应(参考图7)时对比一下,看行为有何不同。

图 7 检查修改:通过发送if-modified-since头,服务器将会使用一个表示自时间戳指定时间以来是否发生了变化的值进行响应 
图 7 检查修改:通过发送if-modified-since头,服务器将会使用一个表示自时间戳指定时间以来是否发生了变化的值进行响应

在图7中,浏览器使用if-modified-since头发送一个请求,服务器使用304代码进行响应,表示浏览器可以使用缓存,不用发起一个完整的GET请求。

为了全面理解这些头信息的效果,最好的办法是你自己动手实验一翻,使用各种不同的头信息组合,并观察它们的行为,分析头信息的一个好工具是Wfetch。

自己动手的方法

正如前面给出的建议,自己动手(DIY)的方法并不总是捷径,专门提供CDN加速的产品和解决方案可以满足不同类型的需求。但如果你要开发的是一个内部使用的产品,可以提供帮助的可能只有Squid了,Squid被用作许多产品的一个组成部分,许多ISP也在使用它。例如,在Java应用程序中,Squid可以被用作Tomcat服务器的代理,Squid提供的不仅仅是HTTP缓存,但关于它的完整介绍已经超出了本文的范围,请读者自行搜索相关文章,可以在Wikimedia看到另一个使用Squid的例子。

HTTP压缩

缓存仅仅是提高Web应用程序性能的方法之一,压缩是另一个关键方法,HTTP压缩在内容发送到客户端之前将其压缩,在客户端和服务器端都有压缩功能,当服务器交付的是压缩内容时,由浏览器进行解压,这样可以节约宝贵的带宽,减少成本和提高响应时间。

浏览器使用值为gzip的accept-encoding—typically头宣称它们支持压缩,服务器使用content-encoding头指定应答数据的编码,例如,如果使用的是gzip格式进行压缩,服务器应该使用值为gzip的content-encoding 头进行响应。

服务器检查响应的MIME类型,只压缩那些通过压缩可以获得好处的类型,如文本文件、HTML和PDF文件,图像格式如gif文件不会从压缩技术获得什么好处,因为gif本身已经是压缩格式了,视频文件以及其它预压缩的二进制文件也不会从压缩功能获得好处。

注意:代理服务器应该和来源服务器支持同类型的压缩。

总体而言,结合缓存和压缩功能可以提高Web应用程序的性能,因此还提高了应用程序的可扩展性。

原文:A Guide to Caching and Compression for High Performance Web Applications

作者:Puneet Sangal

【编辑推荐】

  1. 高性能、高流量互联网应用架构设计实战原则
  2. 高性能Web应用的六个好习惯
  3. 小规模低性能低流量网站架构设计
  4. 大型网站架构不得不考虑的10个问题
  5. 大中型网站架构探秘
责任编辑:yangsai 来源: 51CTO.com
相关推荐

2011-07-05 15:39:50

FTTH

2009-07-31 11:41:12

光纤连接数据中心

2020-03-23 14:35:28

前端架构应用程序

2009-05-25 10:18:20

2009-12-04 12:26:13

2017-11-28 17:14:16

华为云

2009-04-03 11:26:12

AMD上海皓龙

2011-11-28 13:53:03

2018-11-12 11:12:46

2013-09-25 17:31:08

Storwize V5虚拟化存储

2010-04-07 16:13:04

双层宽带无线接入

2016-03-13 17:35:18

2017-04-25 13:53:38

戴尔数据中心服务器

2012-03-01 17:17:30

2022-08-17 14:19:05

高性能计算

2013-01-17 13:26:01

华为光纤线缆解决方案

2009-01-07 01:34:10

SunHPC高性能计算

2012-08-03 15:51:37

HillstoneNAT

2019-03-14 15:38:19

ReactJavascript前端

2013-03-28 13:08:15

Web缓存
点赞
收藏

51CTO技术栈公众号