近期,笔者维护的varnish服务器,不按期出现503错误,按照以往经验,调整超时时间、请求和响应header 正文缓冲区大小,均无解。缓存
而后,只有从varnish自己的行为入手,在varnish机器上启动varnishlog 观察日志,发现有一处异常服务器
ObjHeader Content-Length: 164curl
Fetch_Body 3 length stream性能
Gzip Gunzip error: -3 (incorrect header check)fetch
FetchError Invalid Gzip data: incorrect header checkurl
Gzip u F - 2 0 0 0 0spa
从字面上看,是gzip数据格式致使的,而后就反复猜测,有多是源服务器返回了错误的gzip数据,使用curl访问源服务器:命令行
curl -i -H "Accept-Encoding:gzip" -H "Host:域名" http://源服务器ip/文件路径 设计
输出结果:日志
根据源服务器的响应header Content-Encoding:gzip 明确告诉咱们,正文部分已经使用gzip压缩,可是观察输出,却很诡异,输出的倒是明文的未压缩过的内容,但最后一行,全是空字符,最后一个字符,却是很像是gzip压缩过的内容,说明服务器欺骗了咱们,虽然告诉咱们内容是gzip压缩过的,但实际上倒是不正确的gzip结果。
而后,咱们再尝试获取不压缩的内容:
curl -i -H "Host:域名" http://源服务器ip/文件路径
此次服务器返回了没有压缩过的内容,明显是正确的了。
分析结果:
默认状况下,不管客户端是否支持gzip, varnish在请求源服务器时,会自动增长Accept-Encoding:gzip指令,期待获取压缩内容
varnish取到结果后,会根据vcl_backend_response事件中的beresp.do_gzip = true/false指令,决定是否把内容gzip压缩后缓存起来(显然压缩后缓存,会节省大量内存或磁盘资源),若是这个指令没有设置,则使用缘由内容缓存,不做压缩任何压缩处理。
不管源服务器是否支持gzip压缩,不管缓存内容是否已经gzip压缩,只要客户端支持gzip压缩,varnish会返回gzip的内容。另外一面,若是客户端不支持gzip压缩,varnish会将缓存的gzip压缩过的内容进行解压,再发送给客户端。
varnish是设计就是以最佳性能为考虑的,因此默认是启用gzip压缩的。
知道这几个原理后,若是源机器返回了非法的gzip内容,咱们能够用如下任何一个方法处理:
让源机器返回正确的gzip内容,或禁止源机器gzip压缩。
让varnish在请求源机器时,指望获取不压缩内容
完全禁止掉varnish的全部gzip压缩功能(向客户端发送不压缩的内容——不管客户端是否支持gzip; 请求源服务器时,指望获取不压缩内容)
以上三个方法,任选 一个,便可解决这个问题:
第2条的配置文件方法(在vcl文件中设置):
sub vcl_backend_fetch {
unset bereq.http.Accept-Encoding;
return (fetch);
}
第3条解决方法:
varnishd启动时,使用-p http_gzip_support=off 彻底关闭掉gzip支持,若是是使用yum安装,可在/et/sysconfig/varnish文件中指定
若是varnish已经启动,不容许重启,则可在运行时修改它, 使用 varnishadm 命令,进入命令行界面,查看参数:
param.show
可直接输入help, 查看扩展的指令, 使用如下命令全局关闭gzip支持:
param.set http_gzip_support off
通过这样处理后,偶尔返回503错误的问题获得了解决。