由一個文件下載卡住引發的故障排查過程

故障現象:

現場反饋,一個導出zip壓縮包的下載功能,卡住847M不動了,滾動條不斷提示,但速度爲0,用的chrome瀏覽器。經,詢問,另外一個導出100多M的文件正常。

排查過程:

首先在家裏進行了測試,模擬了1G的文件進行測試,一切正常。又模擬了2G的文件,顯示內存溢出。可是傳送文件是經過流傳輸的,經過apache 的IOUtils.copy複製到 Http Response的OutPutStream,不會佔用太大內存。

懷疑1:

IOUtils.copy的代碼有問題,經查看源碼,是按4K緩存寫入,沒有問題,懷疑排除。

內存溢出的stack trace分析:

從輸出異常棧中發現了ch.qos.logback.access.servlet.TeeServletOutputStream類,該項目使用了logback的access日誌,經查看源碼,果真是有問題。該類包裝了ServletOutputStream,並重寫了write(byte byteArray[], int offset, int length) 方法,把數據寫入到ServletOutputStream以外,又寫入了BtyeArrayOutputStream進行了緩存,用於日誌輸出。
        underlyingStream.write(byteArray, offset, length);
    baosCopy.write(byteArray, offset, length);
            下面是變量定義
            final ServletOutputStream underlyingStream;
    final ByteArrayOutputStream baosCopy;

解決方案:

關閉access日誌,暫時沒有實施,由於該日誌是在parent項目裏配置的,因此選擇了修改個別代碼,用真實的從包裝類中獲取真實的HttpServletResponse並寫出文件流。

新問題:

解決了內存存溢出出問題,又出現了新的現象,文件超過1G大小就會中斷,後臺服務tomcat報timeout錯誤,可是網速好的狀況下就沒有這個錯誤。由於使用了nginx代理服務,因此是nginx緩存致使的超時問題,proxy_buffering off;把代理緩存關掉問題解決。nginx

故障總結:chrome

相關文章
相關標籤/搜索