測(cè)試環(huán)境在運(yùn)行一段時(shí)間后出現(xiàn)了too many open files捐韩,導(dǎo)致一個(gè)定時(shí)上報(bào)redis的任務(wù)頻繁失敗。
-
執(zhí)行命令ps -ef | grep java箩艺,查出進(jìn)程id:13945窜醉。
-
執(zhí)行l(wèi)sof -p 13945
發(fā)現(xiàn)有大量的文件句柄沒(méi)有釋放。懷疑是組內(nèi)小伙伴遍歷文件時(shí)沒(méi)有close導(dǎo)致艺谆。
于是從代碼中尋找蛛絲馬跡榨惰。
發(fā)現(xiàn)原因是delete方法里使用了DirectoryStream并沒(méi)有close。
java8里的Files.newDirectoryStream(p)静汤,通常都使用
try(Files.newDirectoryStream()){
} catch() {
}
的方式琅催,來(lái)避免顯式close釋放資源。
因此判斷當(dāng)時(shí)寫這段代碼的同學(xué)看Files.newDirectoryStream()示例時(shí)虫给,沒(méi)看到close()方法誤以為不需要釋放文件就直接進(jìn)行使用藤抡。導(dǎo)致了too many open files的異常。
另外需要注意的是抹估,在try()中打開(kāi)的文件缠黍,不要執(zhí)行刪除操作,否則同樣會(huì)導(dǎo)致句柄無(wú)法釋放問(wèn)題药蜻。例如:
try(InputStream inputStream = new FileInputStream(new File(path))) {
// doSomething();
} catch(Exception e) {
}finally{
Files.deleteIfExists(Paths.get(path));
}
會(huì)導(dǎo)致如下結(jié)果:
總結(jié):
遇到too many open files時(shí)瓷式,
- 執(zhí)行 lsof -p <pid>,查看該進(jìn)程打開(kāi)的句柄
若句柄數(shù)不正常语泽,則根據(jù)打開(kāi)的句柄檢查不正常的原因贸典,若句柄正常,則進(jìn)行如下第二步踱卵。 -
執(zhí)行 unlimit -a廊驼,查看open files(最大允許打開(kāi)文件數(shù))
linux默認(rèn)為1024,可通過(guò)ulimit -n命令進(jìn)行數(shù)量調(diào)整。
例:ulimit -n 4096
非root用戶最大只能設(shè)置到4096妒挎,需要更多的話需要root權(quán)限绳锅。