故障现象:
现场反馈,一个导出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;把代理缓存关掉问题解决。
故障总结:
转载于:https://blog.51cto.com/luhaiyou/2333349