带有边框的内容合成包括

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数据流中的反向引用不能指向它自己的部分之外。

压缩比受到影响的另一种情况是将未压缩片段插入到压缩响应中。