问题现象:docker上运行的微服务显示no space left on device
先上结论:此微服务的主体功能是上传文件到华为云服务obs进行保存。上传方法是使用multipartFile,磁盘空间一直上涨是使用InputStream stream = multipartFile.getInputStream()后,没有调用stream的close()方法导致的。
定位阶段1
(1)首先登录进docker,使用命令 df -h 进行查询显示挂载/的磁盘已满
(2)进根目录长度,使用du -sh *命令查询查询,想要确认是什么路径下的文件把磁盘空间耗尽。结果显示只占用了几百M空间
疑问:linux文件系统磁盘空间占满,df与du查询不一致
百度了一下df和du不一致原因。删除文件时,如果还有进程占用着此文件,磁盘是不会释放这部分的空间。详细原因可以看这个链接:https://cloud.tencent.com/developer/article/1857432?from=15425
通过lsof命令查询是什么进程占用文件,导致文件系统删除失败,查询到是微服务的java进程。那就是代码存在问题,查看文件存储的路径是:Temp\tomcat.8443.4503940563026842881\work\Tomcat\localhost\ROOT\temp。
定位结论:是文件上传时,会将文件缓存到这个路径下。
定位阶段2:
(1)本地起这个java微服务,查看本地临时路径,上述的Temp\tomcat.8443.4503940563026842881\work\Tomcat\localhost\ROOT\temp路径,文件是否残留未删除。此路径上传完成会进行删除。微服务自己写的代码不涉及缓存本地以及删除操作,可以确认是框架自身实现的。
初步结论:代码是使用MultiPartFile进行上传的,初步怀疑是文件上传后,未调用这个MultiPartFile类的close或者delete方法导致的。
定位阶段3:
(1)查看MultiPartFile类的方法,查看是否有上述提到的MultiPartFile相关方法,没有找到类似方法。这个怀疑点被排除。又怀疑是不是少加了配置项导致的。通过对上传代码进行注释,空方法执行多次,不会出现df和du不一致问题。
(2)那就是自身代码问题。查看multipartFile类使用的getInputStream()方法可能导致此问题。经过试验确认确实这个导致的,InputStream未调用close()方法导致。

总结:如果不关闭文件流,则该文件被占用,就无法删除