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。