1、问题排查(如果没有什么相关工具可用,就比如我不知道用什么插件来排查,这就需要对业务了解)
查看某个进程下打开文件数量,虽可以设置文件打开数量,但不治本。
是因为并发太多的原因吗,修改核心线程数减少一半10改为3
发现并没有解决,再次宕机
继续排查发现这个进程打开的文件数达到3000后宕机(已经确定和ftp下载有关)
打开代码
测试下载方法
发现下载速度超快(万兆网)300张图片300M时间
2021-12-19 00:07:06.155 [schedule-pool-3] INFO c.b.utils.time.Times - [test,24] - 结束:00:07:06.155
2021-12-19 00:07:06.155 [schedule-pool-3] INFO c.b.utils.time.Times - [test,26] - 耗时:1.996秒
好像看不出问题
继续排查,在下载完成后(其实是上面的方法执行完,而图片可能因为网络原因阻塞)
有些图片的大小是0KB,而目标服务器上在告诉我可以下载之前也确实有该图片。那么问题确定
图片没有下载完成,而我默认它下载完成了,最终导致文件打开的越来越多,系统宕机
解决办法:
修改下载方法(将原来的一个连接下多个图片改为一个连接下一个图片)
public boolean downloadFile(String destDir, String destFile, String localDir) {
log.info("=============" + destDir + "====" + "===" + destFile + "+====" + localDir);
boolean result = false;
if (!connect()) {
return result;
}
File localDirFile = new File(localDir);
checkLocalDirExists(localDirFile);
OutputStream os = null;
ftpClient.enterLocalPassiveMode();
try {
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.changeWorkingDirectory(destDir);
ftpClient.enterLocalPassiveMode();
FTPFile[] ftpFiles = ftpClient.listFiles();
// if (destFile == null) { ########## bug toomanyopenfiles
// log.info(" === currentThreadName === " + Thread.currentThread().getName() + "\n" + " === imgCount ===" + ftpFiles.length);
// for (FTPFile file : ftpFiles) {
// File localFile = new File(localDirFile, file.getName());
// os = new FileOutputStream(localFile);
// ftpClient.retrieveFile(file.getName(), os);
InputStream inputStream = ftpClient.retrieveFileStream();
inputStream.close();
ftpClient.completePendingCommand();
// os.flush();
// result = true;
log.info("downLoading.... " + destDir + "/" + file.getName());
// }
// } else {
log.info(" === currentThreadName === " + Thread.currentThread().getName() + "\n" + " === FileCount ===" + ftpFiles.length);
for (FTPFile file : ftpFiles) {
if (destFile.equalsIgnoreCase(file.getName())) {
log.info(" === TMS IncludeThisFile === " + "tms local file_name,{} ", file.getName());
File localFile = new File(localDirFile, file.getName());
os = new FileOutputStream(localFile);
ftpClient.retrieveFile(file.getName(), os);
os.flush();
result = true;
// log.info("downLoading...." + destDir + "/" + file.getName());
break;
}
}
// }
} catch (Exception exception) {
log.info("######### download error xml error xml_name: " + destFile + " destDir: " + destDir + " localDir: " + localDir);
exception.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
// ftpClient.completePendingCommand();
} catch (IOException exception) {
exception.printStackTrace();
}
}
disconnect();
}
return result;
}
加入超时时间保证图片下载不会因为网络原因一直阻塞
public boolean connect() {
if (ftpClient.isConnected()) {
return true;
}
try {
ftpClient.connect(ftpConfig.getHost(), ftpConfig.getPort());
ftpClient.login(ftpConfig.getUserName(), ftpConfig.getPassWord());
int replyCode = ftpClient.getReplyCode();
ftpClient.setControlKeepAliveTimeout(60);
ftpClient.setDataTimeout(3000);
ftpClient.setDefaultTimeout(3000);
ftpClient.setSoTimeout(10000);
if (!FTPReply.isPositiveCompletion(replyCode)) {
ftpClient.disconnect();
log.info("FTP connect failed.");
return false;
}
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
LOCAL_CHARSET = "UTF-8";
}
ftpClient.setControlEncoding(LOCAL_CHARSET);
} catch (IOException exception) {
exception.printStackTrace();
return false;
}
return true;
}
凌晨3点
收工