記一次下載大文件存在數據異常問題排查

最近遇到了一個很詭異的問題,有用戶反饋從文件下載服務測試環境下載一個視頻文件,每次MD5都不同。。。html

對於文件下載服務來講,下載文件內容錯亂是個很嚴重的問題了,可是以前一直也沒遇到過文件內容錯亂的問題。看了一下問題文件,是一個視頻文件,大小爲1.08GB。第一個反應就是多是一個大文件下載纔會觸發的問題。接着問用戶如何發現這個問題的,答曰由於這個視頻文件播放到最後很卡,第二個反應是下載到最後存在數據錯亂。nginx

本身測試了一下,測試環境是100%復現,每次的MD5都是不同的。改用另外的大於1G的文件,同樣能復現,排除了特定文件的可能。接着測試500MB的文件和900MB,發現沒問題,推測問題是出在大於1GB的文件上。可是,生產環境卻沒有這個問題。。。git

本地起Tomcat測試,居然發現沒有復現,結合該應用穩定運行多年,線上也沒有人反饋文件異常問題,推測應用自己的邏輯應該是正常的。懷疑的焦點轉移到了Nginx上。直接訪問測試環境的Tomcat,發現也是正常的,肯定是Nginx問題。github

查看Nginx日誌,發現有很重要的信息:web

2019/06/28 11:28:27 [error] 15032#15032: *5973942305 upstream prematurely closed connection while reading upstream, client: 192.168.237.155, server: debug.web.com, request: "GET /v0.1/static/test_mzb/bigtest-d072bc5950f767009175668f781faaf2.rar HTTP/1.1", upstream: "http://172.xx.xx.xx:8092/v0.1/static/test_mzb/bigtest-d072bc5950f767009175668f781faaf2.rar", host: "debug.web.com"

upstream prematurely closed connection while reading upstream這個錯誤信息的意思是Nginx讀取Tomcat請求時,後端服務關閉了鏈接。網上找到了對應錯誤的討論:Upstream prematurely closed connection while reading upstream · Issue #5706 · owncloud/client,這篇issue中,有人說經過設置proxy_request_buffering off;proxy_buffering off;能夠解決這個問題。經過這個線索,懷疑是Nginx的緩存功能致使的問題。後端

查看Nginx文檔,Module ngx_http_proxy_module,其中描述了在做爲代理服務器時,是否緩存響應的相關配置。總的開關配置是proxy_buffering,表示是否開啓反向代理服務對Response的緩存,默認開啓。開始緩存時,Nginx會以最快的速度從後端服務讀取Response內容,緩存到緩衝區中,緩衝區的大小由proxy_buffer_sizeproxy_buffers配置項指定。若是緩衝區沒法裝下全部的響應,則響應的內容會寫入到緩存文件中,緩存文件的最大大小由proxy_max_temp_file_size配置項指定,默認爲1G。Nginx這個緩存行爲會進行到Response讀取完畢,或者是緩存文件寫滿。緩存

這個緩存文件大小爲1G,與出問題的文件是大於1G相吻合。因此能夠推論問題的緣由是由於用戶下載文件,Nginx會以最快速度從Tomcat獲取文件流,由於Nginx與Tomcat處於一個內網,帶寬很高,很快就會把1G的緩存文件寫滿,而後用戶慢慢下載,當用戶下載完這緩存的內容後,Nginx繼續從Tomcat獲取剩餘的內容,可是這會兒鏈接由於長時間沒有讀寫過時關閉了,致使Nginx提示upstream prematurely closed connection while reading upstream錯誤。至於爲何用戶會繼續下載到後續的錯誤字節數據,這個要看Nginx的具體代碼才能清楚了。服務器

經過將proxy_max_temp_file_size配置爲2G,發現問題解決了,能夠肯定是這個問題。測試

參考資料

本文獨立博客地址:記一次下載大文件存在數據異常問題排查 | 木杉的博客.net

相關文章
相關標籤/搜索