記一次下載大文件存在數(shù)據(jù)異常問題排查

最近遇到了一個(gè)很詭異的問題,有用戶反饋從文件下載服務(wù)測試環(huán)境下載一個(gè)視頻文件,每次MD5都不一樣。。。

對(duì)于文件下載服務(wù)來說,下載文件內(nèi)容錯(cuò)亂是個(gè)很嚴(yán)重的問題了,但是之前一直也沒遇到過文件內(nèi)容錯(cuò)亂的問題??戳艘幌聠栴}文件,是一個(gè)視頻文件,大小為1.08GB。第一個(gè)反應(yīng)就是可能是一個(gè)大文件下載才會(huì)觸發(fā)的問題。接著問用戶如何發(fā)現(xiàn)這個(gè)問題的,答曰因?yàn)檫@個(gè)視頻文件播放到最后很卡,第二個(gè)反應(yīng)是下載到最后存在數(shù)據(jù)錯(cuò)亂。

自己測試了一下,測試環(huán)境是100%復(fù)現(xiàn),每次的MD5都是不一樣的。改用另外的大于1G的文件,一樣能復(fù)現(xiàn),排除了特定文件的可能。接著測試500MB的文件和900MB,發(fā)現(xiàn)沒問題,推測問題是出在大于1GB的文件上。但是,生產(chǎn)環(huán)境卻沒有這個(gè)問題。。。

本地起Tomcat測試,竟然發(fā)現(xiàn)沒有復(fù)現(xiàn),結(jié)合該應(yīng)用穩(wěn)定運(yùn)行多年,線上也沒有人反饋文件異常問題,推測應(yīng)用本身的邏輯應(yīng)該是正常的。懷疑的焦點(diǎn)轉(zhuǎn)移到了Nginx上。直接訪問測試環(huán)境的Tomcat,發(fā)現(xiàn)也是正常的,確定是Nginx問題。

查看Nginx日志,發(fā)現(xiàn)有很重要的信息:

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這個(gè)錯(cuò)誤信息的意思是Nginx讀取Tomcat請(qǐng)求時(shí),后端服務(wù)關(guān)閉了連接。網(wǎng)上找到了對(duì)應(yīng)錯(cuò)誤的討論:Upstream prematurely closed connection while reading upstream · Issue #5706 · owncloud/client,這篇issue中,有人說通過設(shè)置proxy_request_buffering off;proxy_buffering off;可以解決這個(gè)問題。通過這個(gè)線索,懷疑是Nginx的緩存功能導(dǎo)致的問題。

查看Nginx文檔,Module ngx_http_proxy_module,其中描述了在作為代理服務(wù)器時(shí),是否緩存響應(yīng)的相關(guān)配置??偟拈_關(guān)配置是proxy_buffering,表示是否開啟反向代理服務(wù)對(duì)Response的緩存,默認(rèn)開啟。開始緩存時(shí),Nginx會(huì)以最快的速度從后端服務(wù)讀取Response內(nèi)容,緩存到緩沖區(qū)中,緩沖區(qū)的大小由proxy_buffer_sizeproxy_buffers配置項(xiàng)指定。如果緩沖區(qū)無法裝下所有的響應(yīng),則響應(yīng)的內(nèi)容會(huì)寫入到緩存文件中,緩存文件的最大大小由proxy_max_temp_file_size配置項(xiàng)指定,默認(rèn)為1G。Nginx這個(gè)緩存行為會(huì)進(jìn)行到Response讀取完畢,或者是緩存文件寫滿。

這個(gè)緩存文件大小為1G,與出問題的文件是大于1G相吻合。所以可以推論問題的原因是因?yàn)橛脩粝螺d文件,Nginx會(huì)以最快速度從Tomcat獲取文件流,因?yàn)镹ginx與Tomcat處于一個(gè)內(nèi)網(wǎng),帶寬很高,很快就會(huì)把1G的緩存文件寫滿,然后用戶慢慢下載,當(dāng)用戶下載完這緩存的內(nèi)容后,Nginx繼續(xù)從Tomcat獲取剩余的內(nèi)容,但是這會(huì)兒連接因?yàn)殚L時(shí)間沒有讀寫過期關(guān)閉了,導(dǎo)致Nginx提示upstream prematurely closed connection while reading upstream錯(cuò)誤。至于為什么用戶會(huì)繼續(xù)下載到后續(xù)的錯(cuò)誤字節(jié)數(shù)據(jù),這個(gè)要看Nginx的具體代碼才能清楚了。

通過將proxy_max_temp_file_size配置為2G,發(fā)現(xiàn)問題解決了,可以確定是這個(gè)問題。

參考資料

本文獨(dú)立博客地址:記一次下載大文件存在數(shù)據(jù)異常問題排查 | 木杉的博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容