带有边框的内容合成包括¶
Varnish可以通过组合不同的页面来创建网页,称为 fragments ,一起放在一页中。这些 fragments 可以有单独的缓存策略。如果您有一个Web站点,其中的列表显示了站点上最受欢迎的五篇文章,则此列表可能会被缓存为 fragment 并包含在所有其他页面中。
如果使用得当,该策略可以极大地提高命中率并降低服务器的负载。
在Varnish中,我们只实现了ESI的一个很小的子集,因为大多数其余的ESI规范工具使用VCL::
esi:include
esi:remove
<!--esi ...-->
未实现基于变量和Cookie的内容替换。
Varnish不会处理HTML注释中的ESI指令。
示例:ESI:INCLUDE¶
让我们看一个如何使用这一点的例子。这个简单的CGI脚本输出日期::
#!/bin/sh
echo 'Content-type: text/html'
echo ''
date "+%Y-%m-%d %H:%M"
现在,让我们有一个包含ESI INCLUDE语句的HTML文件::
<HTML>
<BODY>
The time is: <esi:include src="/cgi-bin/date.cgi"/>
at this very moment.
</BODY>
</HTML>
要使ESI正常工作,您需要在VCL中激活ESI处理,如下所示:
sub vcl_backend_response {
if (bereq.url == "/test.html") {
set beresp.do_esi = true; // Do ESI processing
set beresp.ttl = 24 h; // Sets the TTL on the HTML above
} elseif (bereq.url == "/cgi-bin/date.cgi") {
set beresp.ttl = 1m; // Sets a one minute TTL on
// the included object
}
}
请注意 set beresp.do_esi = true;
对于包含的片段,不是必需的,应该避免,除非它们还包含 <ESI::include …/>
指示。
示例:esi:Remove和<!--esi...-->¶
这个 <esi:remove> 和 <!--esi ... --> 无论ESI是否可用,构造都可用于显示适当的内容,例如,您可以在ESI可用时包含内容,或在ESI不可用时链接到内容。ESI处理器将在处理页面时删除开头(“<!--esi”)和结尾(“-->”),同时仍在处理内容。如果页面未被处理,它将保持不变,成为一个HTML/XML注释标记。ESI处理器将删除 <esi:remove> 标记及其包含的所有内容,允许您仅在页面未进行ESI处理时呈现内容。例如::
<esi:remove>
<a href="http://www.example.com/LICENSE">The license</a>
</esi:remove>
<!--esi
<p>The full text of the license:</p>
<esi:include src="http://example.com/LICENSE" />
-->
如果它失败了会发生什么?¶
默认情况下,片段必须具有 resp.status
200或206或包含它们将导致父请求中止。
同样,如果片段是流提取,并且提取失败,则父请求中止。
如果包括合成片段,即在中创建的片段 vcl_backend_error{}
或 vcl_synth{}
,您必须设置 (be)resp.status
至之前的200 return(deliver);
我们说“Abort”而不是“Fail”,因为当Varnish开始插入片段时,HTTP响应头早已被发送,并且不再可能更改父请求的 resp.status
到5xx,所以发出有问题的信号的唯一方法是关闭连接。
但是,可以允许个人 <ESI:include…
要在出现故障时继续,请设置:
param.set feature +esi_include_onerror
而对这些具体内容进行标记包括:
<ESI:include src="…" onerror="continue"/>
ESI片段也可以使用ESI-Includes吗?¶
是的,但深度受到 max_esi_depth
参数,以防止无限递归。
对JSON和其他非XML内容进行ESI¶
Varnish将偷看对象的第一个字节,如果它不是“<”,则认为您并不是真的想要ESI处理它。您可以通过以下方式禁用此检查:
param.set feature +esi_disable_xml_check
忽略ESI对象中的BOM表¶
如果后端输出Unicode Byte-Order-Mark作为响应的第一个字节,则“<”检查将失败,除非您设置::
param.set feature +esi_remove_bom
无效的XML上的ESI¶
ESI解析器希望XML的格式合理良好,但如果您是包含非XML文件的ESI,这可能会失败。您可以通过设置::使ESI解析器忽略除ESI标记之外的任何内容
param.set feature +esi_ignore_other_elements
ESI包括HTTPS协议¶
如果ESI:Include标签指定HTTPS协议,默认情况下它将被忽略,因为Varnish无法通过加密获取它。如果希望Varnish像获取其他任何东西一样获取它们,请设置::
param.set feature +esi_ignore_https
部分响应的ESI(206)¶
Varnish支持范围请求,但一般情况下,部分响应在ESI上下文中没有意义。
如果您真的知道自己在做什么,请将206更改为200::
sub vcl_backend_response {
if (beresp.status == 206 && beresp.http.secret == "swordfish") {
set beresp.do_esi = True;
set beresp.status = 200;
}
}
ESI和RETURN(VCL(...))¶
如果原始客户端请求使用切换到不同的VCL return(vcl(...))
在……里面 vcl_recv
,任何ESI:INCLUDE-请求仍将在与原始DID相同的VCL中开始, not 在它切换到的那一家。
ESI和GZIP压缩¶
Varnish的ESI实现自动处理gzip压缩,无论它是如何混合的:父请求可以压缩或解压缩,片段可以压缩或解压缩,一切都会解决。
Varnish是这样做的,分别压缩ESI响应的所有部分,并在交付过程中将它们快速缝合在一起,这对压缩比有负面影响。
当你 set beresp.do_esi = True;
对于gzip格式的响应,它将在提取过程中部分地解压缩和重新压缩。
分部分压缩减少了删除冗余的机会,因为gzip数据流中的反向引用不能指向它自己的部分之外。
压缩比受到影响的另一种情况是将未压缩片段插入到压缩响应中。