【发布时间】:2014-05-06 02:36:55
【问题描述】:
我的一个客户不断抱怨他们的网站不够快...这对我来说有点奇怪,因为几个月前他们雇用我时,他们无法让服务器保持 24 小时运行,因为它缓存太多并且内存不足。因此,我删除了大部分缓存,优化了他们的数据库,将它们放在了至少 5 倍强大的新服务器上(RAM 量和处理器速度——它们现在拥有几乎相同时钟速度的 4 倍处理器) ,并且他们抱怨“我们的网站从未如此缓慢!”。
因此,我正在浏览所有 Google 所说的可以提高性能的事情的清单,希望最终他们会对此感到满意,或者他们会意识到他们的网站正在做很多工作,并且他们的服务器有限制,有些页面需要几秒钟才能加载,就像你不能在一个小时内手工建造整辆汽车一样。我所做的所有研究表明,如果我指定了 Cache-Control、Expires 和 Last-Modified 标头,Firefox 应该使用它的缓存,但无论我如何在 ColdFusion 中设置它们,Firefox 和 Chrome 都拒绝使用缓存。我可以手动设置 304 响应标头,如果尚未缓存图像,这似乎会导致 Firefox 不返回任何内容。 (?!!)
所以我有这个代码。很简单。几乎所有文档都说它应该是。并且 FireBug 始终报告(尽管重新启动、缓存清除、强制重新加载等)内容是在几秒钟前创建的,而不是像我在 cfheader 中设置的 7 天前。另一方面,Chrome 将 Last Modified Date 报告为一周前,但随后报告请求标头中的 max-age 为 0。 (?!!)(在 Chrome devtools 中启用了缓存,所以我知道不是这样。)来自 Chrome 的响应标头显示了正确的 max-age 值。 (编辑:这让我对 FireBug 和 Chrome 的开发者工具中的数据显示感到困惑 - 所以事实证明,是的,两个浏览器都正确接收了响应标头。)
<cfheader name="Content-Type" value="image/png" />
<cfheader name="Cache-Control" value="max-age=604800, private, must-revalidate" />
<cfheader name="Expires" value="#getHTTPTimeString(dateadd('d', 1, now()))#" />
<cfheader name="Last-Modified" value="#getHTTPTimeString(dateadd('d', -7, now()))#" />
....
<cfcontent type="image/png" variable="#toBinary(img)#" />
鉴于 Chrome 正确报告了响应标头,这似乎不像我读过的 HTTP 标准 教程(声称基于标准)所说的那样工作应该工作......但我不能确定。我当然不是 HTTP 专家,所以我可能会忽略一些东西。这不是一个复杂的应用程序。这就是为什么我如此沮丧和扯掉我的头发的原因。
非常感谢任何帮助。谢谢!
编辑
因此,要提供有关已接受答案的更多信息,这是我在 ColdFusion 中的解决方案。上面的代码基本上保持在页面中(例如 index.cfm)。然后利用浏览器返回的缓存提示,我在 Application.cfc 中有类似的东西
<cfcomponent output="false">
<cffunction name="onRequest" access="public" output="true">
<cfargument name="targetPage" type="string" required="true" />
<cfset var modDate = getIfMOdifiedSince() />
<cfif isDate(modDate) and datediff('d', modDate, now()) lte 7>
<!--- the browser has a cached copy that's less than a week old, let the browser use it --->
<cfheader name="Content-Type" value="image/png" />
<cfheader statuscode="304" statustext="Not Modified" />
<cfelse>
<!--- the browser hasn't seen it in 7 days (or possibly ever), return the image --->
<cfheader name="Last-Modified" value="#getHTTPTimeString(now())#" />
<cfinclude template="#targetPage#" />
</cfif>
</cffunction>
<cffunction name="getIfModifiedSince" access="private" output="false" returntype="string">
<cfset var head = getHTTPRequestData().headers />
<cfreturn iif(structKeyExists(head, "if-modified-since"), "head['if-modified-since']", de("")) />
</cffunction>
</cfcomponent>
这可能比您需要的要简单一些。这个特定的代码实际上并没有检查图像是否被修改,因为这不是我们真正担心的事情。这个应用程序只提供一组特定的图像,所以我们知道这个应用程序提供的任何东西都是 PNG,所以我们可以安全地将内容类型标题设置为 image/png,因为图像真的不会改变,我不会打扰任何类型的实际日期检查。我可能真的可以让图像无限期地存在,但现在我让浏览器一次拥有它们一周。随着他们业务的增长,我可能会在以后增加该持续时间。
这项工作的真正症结在于,使缓存工作的事情是 onRequest() 方法检查 if-modified-since 请求标头,并且当存在时并在所需的时间跨度内,它通过 NOT 截断整个请求包括目标页面(因此不会执行任何剩余的页面代码),而是仅设置 403 Not Modified 状态响应标头。
从长远来看,正如我所怀疑的那样,这实际上是一件非常简单的事情,显然只是被创建在线教程的人广泛误解。
【问题讨论】:
-
您是否尝试过像 fusion-reactor.com 这样的分析工具 - 他们有 14 天的免费试用期 - 这可以帮助解决原始错误,允许您删除缓存标头
-
我们正在服务器上运行 fusion-reactor...但是 CF 没有抛出错误,所以我不确定这有什么帮助?
-
关于
fusion-reactor的建议是,如果你修复了网站性能不佳的问题,你就不需要那些让你痛苦的缓存标头。修复缓存头实际上并不能修复服务器性能,它只是掩盖了它。 -
他们的网站是面向公众的吗?你能链接到他们的网站吗?
-
修复图像缓存将减少服务器上的负载,因此确实总体上具有提高性能的潜力。
标签: performance caching coldfusion