其實還是這個老問題: 記一次文件下載丟包填坑之旅 http://www.cnblogs.com/syjkfind/p/5281677.html 即使現在只有haproxy-nginx-磁碟文件 比較少的轉發,但文件特別大,還是偶有文件不完整的問題。 從現象上看,瀏覽器響應是200沒問題,curl命令 ...
其實還是這個老問題:
記一次文件下載丟包填坑之旅 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層有比較好的抓包或監控,問題可以定位得更快速更精確(然而是生產環境,你懂的)。再有就是網路鏈路這種東西就是個幽靈,如何重現也是個難題。幸得,各種查閱資料以及對著日誌對著配置各種“格物致知”,終於在“大膽假設小心求證”中找到了出路。
至此,問題也算是相對圓滿地解決了。