2009年5月17日,星期日

优化,BLOB缓存和HTTP 304

最近,关于将站点使用的静态资产存储在何处(图像,CSS,JS文件等),有一个有趣的小辩论。概括地说,这两种方法的特点是:

  • 以开发人员为中心-将资产存储在文件系统中,也许在12个配置单元中
  • 以作者为中心-将资产存储在内容数据库中,也许存储在发布站点随附的样式库中

不用说,这些选项会根据您的要求提供不同的优缺点- 服务é Hermans 提供了很好的分析 打包还是不打包:这就是问题。但是,我想提出另一点争论:性能,特别是针对匿名用户的性能。通常,这是我深为关注的受众,因为我工作的某些WCM网站的预测比例通常为80%的匿名用户与20%的经过身份验证的用户。最近,有人要求我帮助优化以MOSS为基础的业绩不佳的航空公司网站-通常,问题是多方面因素的结合,但是影响最大的一项是决定将资产存储在一个位置而不是另一个位置。在这篇文章中,我将解释对性能的影响以及在构建网站时为什么要考虑这一点。

问题

首次加载后,网站上使用的大多数静态文件应从用户的本地浏览器缓存中提供("临时网络文件")-如果没有这个功能,网际网路将非常缓慢。考虑一下与正常情况相比,进行硬刷新(ctrl + F5)时网页加载的速度有多慢-这是因为所有图像都被强制重新下载而不是从浏览器缓存中提供。不幸, 用于存储在某些常见SharePoint库/库中的文件(即以作者为中心的方法) 的SharePoint不能完全解决这个问题 在某些情况下- 的增益是存在的,但是尽管图像在本地,但浏览器仍然会请求图像-对话是这样的(对于页面上的每个图像!):

浏览器: 我需要这张图片-上次我在[日期/时间]到来时将其缓存了,但据我所知,此后一直在更改。
服务er: 不需要花花公子,它没有更改,因此只需使用本地副本(以HTTP 304的形式-"Not modified")
浏览器: 很公平,欢呼。

这实际上是因为文件未与"cacheability"开始的HTTP标头。 不用说,当您在页面上引用了30多个图像/ CSS / JS文件时,这会增加页面加载的大量时间-根据我的经验(在某些情况下)可能是几秒钟,这当然是一笔大数目。如果说用户在欧洲,但服务器在美国,那么突然之间,我们需要解决这种网络聊天问题。不用说,在大多数情况下,我们很乐意将这些文件缓存一段时间,因为它们不会经常更改,因此,我们可以获得更好的性能。

解决方案(针对 一些 的SharePoint库*)

迈克·霍德尼克在他的强烈推荐文章中指出了我们解决方案的一部分 消除"304"SharePoint Web文件夹资源的状态代码。本质上, 的SharePoint的BLOB缓存功能 保存日期,因为它通过"max-age"HTTP标头上的值,表示浏览器知道在此日期之前可以使用文件的本地副本。这仅在启用BLOB缓存时发生 and has the 最大年龄 在 tribute 像这样(此处设置为84600秒= 24小时):

<BlobCache location="C:\blobCache" path="\.(gif|jpg|png|css|js|aspx)$" maxSize="10" enabled="true" 最大年龄="86400" />

实际上,当我们这样配置BLOB缓存时,实际上是指定可以将静态文件缓存一定的时间,因此"cacheable" header gets added. 但是,Mike所不能涵盖的是,这仅发生在经过身份验证的用户身上 -从通用内容数据库位置(例如样式库和母版页库)提供的文件仍无法正确提供给匿名用户。请注意,虽然这不是所有的SharePoint库-因此我们需要清楚何时发生此问题。

*此问题/解决方案的范围

在深入探讨之前,让我们先停下来思考一下我们正在讨论的内容的范围-该站点具有:

  • 匿名用户
  • 文件存储在 一些 库-我不是百分百确定该模式,但稍后再讨论-但是,样式库和母版页库是已知的罪魁祸首。其他OOTB库(例如SiteCollectionImages) 有问题。

如果您没有这两种情况的组合,则可能没有问题。对于这样做的人,我们现在将仔细研究正在发生的事情,然后再总结最后如何解决该问题。

钻得更深

对于一个网站 确实 结合以上情况,我们可以看到Fiddler的问题-作为 匿名 用户浏览到我已经访问过的页面时,我看到一堆304,这表示浏览器正在重新请求所有这些文件:

BlobCachingDisabled_304s

但是,如果我 已认证 并且导航到同一页面,我只看到实际页面的HTTP 200,没有304:

BlobCachingEnabled_No304s

因此,我们可以得出结论,它适用于经过身份验证的用户,但不适用于匿名用户。

那么,如果我们将文件存储在有问题的库中,我们可以为可怜的匿名用户(可能占大多数)做什么?好吧,这是我不幸的空白。 针对WAN环境优化Office 的SharePoint 服务er TechNet上对此有以下说法:

默认情况下,某些列表不适用于匿名用户。如果有匿名用户访问该网站,则需要为以下列表手动配置权限,以便缓存其中的项目:

  • 母版页画廊
  • 样式库

啊哈!因此,我们需要更改一些权限-很好。这似乎表明它 是的 实际上,可以将正确的缓存头添加到从这些位置提供的文件中。不幸的是,我只是 不能 找到需要更改的权限,并且互联网上没有人(包括TechNet文章)详细说明了什么。唯一的逻辑设置是列表的“匿名访问”选项-默认情况下,这些选项都是清除的,但是添加“查看项”权限(如下所示)不会更改任何内容:

匿名权限

附带说明,上面的设置是(我相信)有效地授予对身份的读取权限,该身份用于匿名访问关联的IIS站点。因此,在IIS 7.0中,我相当确定您可以通过执行以下操作来实现相同的目的:

AddPermsIUsr

因此,当匿名用户被授予“查看项目”权限时,问题不会消失,而我发现与此有关的有趣之处在于,与Fiddler仔细观察后发现了一些不一致之处。下图显示了我第一次匿名浏览到页面,为避免麻烦,我们可以得出以下发现:

  • Files served from the 'SiteCollectionImages' library are given the correct 最大年龄 header (perhaps expected, since 不 one of the known 'problem libraries' e.g. 样式库)
  • Files served from the '_layouts' folder are given a different 最大年龄 header (expected, settings from the IIS site are used here)
  • 一些 files in the 样式库 are in fact given a the correct 最大年龄 header! (not expected) 

MixedHeaders_Anonymous

因此,这里给我留下深刻印象的两个问题是:

  • 为什么大多数文件不是由“样式库”提供的带有正确标题的文件?
  • 为什么SharePoint可以将'max-age'标头添加到'SiteCollectionImages'库中的文件中,而不是添加到'样式库'中?

第一个对我来说是个谜-可能不太重要,但我无法解决。第二个 威力 取决于库的配置方式-“样式库”由“ PublishingResources”功能部件中的声明性XML进行配置,而“ SiteCollectionImages”库则是使用同一功能部件的激活接收器在代码中进行配置的。这可能是关键因素吗?我不知道,但是如果有人能直言不讳,我肯定会很感兴趣-无论是关于这个还是这个谜团"permissions change"使BLOB缓存处理诸如“样式库”之类的库所必需。

结论

这里的主要要点是,对于那些想利用浏览器缓存静态文件(出于性能原因)并拥有匿名用户的站点,我们需要注意按照Mike Hodnick的常规将图像/ CSS / JS文件放置在何处信息。如果我们想使用以作者为中心的方法并将其存储在SharePoint库中,则需要考虑 哪一个 库(并测试)是否存在304问题。另外,我们可以选择将这些文件存储在文件系统上(以开发人员为中心的方法),并使用具有适当缓存设置的虚拟目录来满足我们的需求。我的建议是使用自定义虚拟目录来完全控制此目录,因为“ _layouts”目录中的默认设置("cache for 1 year")不太适合。

10条评论:

匿名 said...

我个人认为这是一个巨大的错误。有人在2007年对这篇文章的评论中注意到了它:
http://blogs.msdn.com/ecm/archive/2006/11/08/how-to-make-your-moss-2007-web-site-faster-with-caching.aspx

我不知道MS无法解决此问题。即使SP2也没有。

泰勒·福尔摩斯说过...

这在浏览器之间是否表现一致?

对于FireFox,当从样式库中提取某些资产时,是的,确实是它获得了私有的Cache-Control,max-age = 0 ...但是在原始文件中还有一个ETag和Last-Modified标头响应。

其他浏览器将提取这些信息,下次发送请求时,它们将发送If-Modified-Since和If-None-Match标头(除了Cache-Control之外)。

当SharePoint获得这些消息时,它将发出适当的响应代码304(未修改)。

可能是此“错误”出现在IE 6/7中,并已在将来的MS浏览器中修复了吗?

将提琴手放一秒钟,然后再看一下FireFox和Tamper数据。新鲜的眼睛可能会改变您的想法。

我最好的,
泰勒

迈克尔·汉斯说过...

我们在www.westernaustralia.com和其他站点上通过使用FilterProxy在反向代理上重写某些缓存头来解决此问题。反向代理位于WFE和Internet之间,并处理所有被分流的内容。由于我们所有站点都是通过代理服务的,这也使生活变得更轻松,因为我们不必在IIS站点级别配置缓存。

我也注意到IE和FF之间的差异(FF似乎总是发出有条件的get,但这可能只是由于浏览器设置引起的)。

克里斯·奥'Brien说过...

@泰勒,@米歇斯,

除非我缺少任何东西,否则在两种浏览器中都会看到相同的行为。如果在IE / Fiddler和FF / Tamper中都检查了对某个样式库文件的请求,则会看到相同的If-Modified-Since和If-None-Match数据。因此,这是一回事,但无论如何-匿名用户首先不是请求/后续请求304发生的问题吗?不管底层标题如何,我肯定关心的是往返 发生,因此减慢了页面加载速度-如果最初正确提供了文件,则浏览器不会发出此请求。

在我看来,像michhes的反向代理方法之类的解决方案是当前解决此问题的唯一方法-我很好奇是否在此实施了该方法,因为服务器位于西澳大利亚州,但站点用户可能位于其他大洲,所以这恰恰是需要哪种优化?

感谢您的评论。

克里斯。

匿名 said...

我在多个浏览器(甚至是IE8)中也看到了这种现象。奇怪的是,经过身份验证的用户确实会根据blobcache中的最大年龄获得最大年龄,而匿名用户的最大年龄却是0。Internet上到处都是匿名用户...
正如克里斯所说的那样,性能瓶颈就是往返。
Perhaps a custom http adapter that adds/changes the 最大年龄 header can also be a solution if there 是 no reverse proxy involved?

克里斯·奥'Brien说过...

使用HTTP模块或类似模块做某事-是的,这是一个好主意。

尽管我猜可能有人认为将文件存储在其他位置会更简单/更有效。不过,如果文件由于某种原因而具有变通方法,还是很不错的 要存储在样式库中,例如用于现有站点。

谢谢,

克里斯。

迈克·霍德尼克说过...

感谢您对我的Blob缓存和304的Chris文章的引用! -迈克

马克西姆·庞巴迪说过...

感谢克里斯的信息,好的帖子。

It'是一个已知的错误'在SharePoint 2010之前尚未修复或计划。'd建议使用其他库来存储您的自定义CSS / JS / XSL。

文件系统文件夹的问题将是在多个服务器之间同步它们,特别是如果允许设计人员修改样式的话。

马克西姆

克里斯·奥'Brien说过...

@Maxime,

啊哈-听到那个很有趣'是已确认的错误,尤其是来自MS人员的错误!

非常感谢您提供的信息。

克里斯。

附言同意如果设计人员需要访问文件,那么Fiddler将显示一个替代库 确实 正确的BLOB缓存可能比文件系统更合适。

杰森·拉穆塔(Jason Ramoutar) said...

克里斯,谢谢你的写信。它'很有帮助,内容丰富。