GZIP和GZIP+ESI在Varnish中的工作方式

首先,您在这里看到的关于GZIP的所有内容都由参数控制:

http_gzip_support

如果您不想让Varnish在压缩方面表现得更聪明,可以将其设置为“Off”。

Http_gzip_Support做些什么

从vclrecv{}发送到‘PASS’或‘PASS’模式的请求不会有任何差异,此处理仅影响缓存命中/未命中请求。

除非vclrecv{}结果为“管道”或“通过”,否则我们将确定客户端是否能够接收gzip格式的内容。这项测试的结果是:

是否有一个提到gZip的Accept-Ending头,如果is有一个q=#数字,它是否大于零。

可以执行gzip的客户端将其标头重写为:

接受-编码:GZIP

而不支持GZIP的客户端将删除其Accept-Ending报头。这确保了在对象创建期间创建Variable:字符串的一致性。

在查找过程中,我们忽略了对象VARIES中的任何“接受编码”:字符串,为了避免对象的gZip和GunZip版本,Varnish可以按需进行GunZip。(我们在查找时实现这一点魔力,以便在启用或不启用gzip支持的情况下,可以使用存储在永久存储中的任何对象。)

Varnish不能进行gzip以外的任何其他类型的压缩,尤其是我们不能进行放气,因为在这种情况下会出现浏览器错误。

在调用VCL_MISTH{}之前,后端请求Accept-Ending始终设置为:

接受-编码:GZIP

即使此特定客户端不支持

始终诱使后端向我们发送gzip格式的内容。

Varnish本身不会压缩任何内容(但见下文),我们相信后端知道哪些内容可以合理地压缩(Html),哪些内容不能压缩(Jpeg)。

如果在vCL_BACKEND_RESPONSE{}中,我们发现我们正在尝试将一个gZip格式的对象传递给一个没有表示愿意接收gZip的客户端,我们将在传递过程中取消压缩该对象。

调谐、微调和翻滚

在vclrecv{}中,您有机会在发生任何其他事情之前修改客户端的Accept-Ending:Header。

在vCL_PASS{}中,客户端Accept-Ending标头被原封不动地复制到后端请求。即使客户端不支持GZIP,也可以强制将A-C头改为“GZIP”,以节省后端和VARNISH之间的带宽,VARNISH会在将对象交付给客户端之前对对象进行GURZIP压缩。

如果您不想让后端对此对象进行压缩,则可以在vclMisse{}中删除“Accept-Ending:gzip”头文件。

在vCL_BACKEND_RESPONSE{}中,有两个新变量允许您在FETCH过程中修改对象的gzip-ness:

设置beresp.do_gan Zip=真;

将在FETCH过程中从后端将VarnishGunZip设置为已压缩的对象。(我不知道你为什么/什么时候会用这个……)

设置beresp.do_gzip=TRUE;

在从后端获取的过程中,如果后端没有向我们发送GZIP格式的对象,将使VARNISH对对象进行GZIP压缩。

请记住,许多内容类型不能合理地压缩为gziped,最明显的是压缩图像格式,如jpeg、png和类似格式,因此典型的用法是:

sub vcl_backend_response {
        if (bereq.url ~ "html$") {
                set beresp.do_gzip = true;
        }
}

GZIP和ESI

首先,注意激活ESI::的新语法:

sub vcl_backend_response {
        set beresp.do_esi = true;
}

在理论上,希望在实践中,当您启用ESI时,上面所读到的所有内容也应该适用,如果不是,它是您应该报告的错误。

但现在的情况要复杂得多。例如,当后端发送一个gZip格式的对象时,我们对其进行ESI处理,并且它包含另一个不是gziped的对象,而我们希望将结果gziped发送到客户端,会发生什么情况?

这里的情况可能会变得非常糟糕,所以让我分阶段解释一下。

假设我们有一个未压缩的对象,我们想要ESI处理。

ESI解析器将遍历对象以查找各种魔术字符串,并生成我们称为Varnish ESI代码的“VEC”的字节流。

VEC包含“跳过234个字节”、“传递12919个字节”、“包含/目标”、“传递122个字节”等指令,并与对象一起存储。

当我们传递具有VEC的对象时,特殊的ESI传递代码解释VEC字符串并将输出按顺序发送到客户端。

当VEC说“Include/foobar”时,我们使用新的URL和可能的host:Header执行相当于重新启动的操作,并调用vclrecv{}等。您可以通过检查VCL中的‘req.esi_Level’变量来判断您处于ESI Include中。

ESI解析后的对象在与上面相同的条件下以gzip‘格式存储:如果后端发送gzip’ed而VCL没有请求do_gan压缩,或者如果后端发送ungzip‘ed而VCL请求do_gzip。

请注意,由于我们需要在GZIP文件中插入刷新和重置点,因此它将略大于相同对象的普通GZIP文件。

当我们遇到gZip‘ed包含不应该压缩的对象时,我们会对它们进行压缩,但当我们遇到应该压缩的对象时,我们会对它们进行gzip压缩,但只有在压缩级别为零的情况下才会进行压缩。

因此,为了避免不必要的工作,并获得最大的压缩效率,您应该:

sub vcl_miss {
        if (object needs ESI processing) {
                unset req.http.accept-encoding;
        }
}

sub vcl_backend_response {
        if (object needs ESI processing) {
                set beresp.do_esi = true;
                set beresp.do_gzip = true;
        }
}

以便后端将这些未压缩的对象发送到Varnish。

您还应该尝试确保所有esi:included对象都是gziped的,方法是让后端执行gziped或让Varnish执行gziped。