其实还是这个老问题:
记一次文件下载丢包填坑之旅 http://www.cnblogs.com/syjkfind/p/5281677.html
即使现在只有haproxy-nginx-磁盘文件 比较少的转发,但文件特别大,还是偶有文件不完整的问题。
从现象上看,浏览器响应是200没问题,curl命令的日志显示是 curl: (18) transfer closed with 204800 bytes remaining to read
字面上理解就是连接已关闭。查相关资料并没有任何有关的答案,说nginx缓冲大小的现象不一样已排除,倒是偶有提到连接关闭。
百思不得其解,直到跟运维同事要到haproxy的配置看了好几遍。。。一个关键字引起了我的注意:http-server-close
【http-server-close】
相关配置参考资料 http://www.cnblogs.com/dkblog/archive/2012/03/13/2393321.html
大意就是haproxy和浏览器保持长连接,但haproxy跟后端服务器采用短连接。
什么是长连接参考资料 http://www.cnblogs.com/cswuyg/p/3653263.html
那么究竟是长连接好还是短连接好?其实要看具体场景。长连接可以节省反复连接的开销,加快响应;短连接则可以加快连接的释放,提高并发的能力。
于是改成了http-pretend-keepalive,好像发生少了很多,再后来使用gzip传输就很少再发生了。当然,偶尔再有发生也是网速的问题,无解了,总不能无限制地加大timeout吧。
再有就是顺带提起的haproxy该用7层http还是3层tcp,大部分资料都是讲http,这里有提到当https转发时得用tcp模式。http://serverfault.com/questions/611272/haproxy-http-vs-tcp
【断点续传】
改成http-pretend-keepalive后,有趣的事情发生了,浏览器得到的响应居然是206,也就是说,长连接的情况下,可以支持断点续传~~~
【开启gzip传输】
nginx本来就是开启支持gzip传输的,可是没生效啊,为什么呢?其实原因很简单,就是响应类型不对。开启支持gzip的格式是plain text和html,但默认类型是application/octet-stream。只要给返回的文件设置类型为text/plain就可以了。开启gzip和设置Content-Type的配置就不多说了。
开启gzip当然是爽到爆了,原来20MB的文本文件传输起来只有1.5MB!当然也有点小问题就是传输编码是chunked,无法知道文件的总大小,无法知道文件是否完整。但是在节省了92%带宽的情况下,都没再听用户提起过传输不成功了。
顺带,验证了一个问题,nginx设置限速,然后下载到一半把浏览器停掉,得到的文件是乱码的,说明gzip是整个文件压缩而不是每片去压缩,残缺的文件改为.zip后解压出来得到的文件则是正确的文本而内容少了后面部分。
再反思整个过程,其实有几分碰运气歪打正着的感觉,如果在haproxy层和nginx层有比较好的抓包或监控,问题可以定位得更快速更精确(然而是生产环境,你懂的)。再有就是网络链路这种东西就是个幽灵,如何重现也是个难题。幸得,各种查阅资料以及对着日志对着配置各种“格物致知”,终于在“大胆假设小心求证”中找到了出路。
至此,问题也算是相对圆满地解决了。