现象
public boolean uploadFile(MultipartFile file, String dst) {
try {
long start = System.currentTimeMillis();
// 创建Hadoop配置对象
Configuration config = new Configuration();
config.set("fs.defaultFS", hdfsUri);
Path dstPath = new Path(ROOT_PATH + dst);
FileSystem fs = dstPath.getFileSystem(config);
// 上传文件到HDFS
InputStream in = new BufferedInputStream(file.getInputStream());
OutputStream out = fs.create(dstPath);
IOUtils.copyBytes(in, out, 128000000, true);
in.close();
// 关闭FileSystem对象
fs.close();
long end = System.currentTimeMillis();
logger.info("文件名称: {} 耗时: {}", dst, end - start);
return true;
} catch (Exception e) {
logger.error("文件:{}, 上传错误!, ", dst, e);
return false;
}
}
以上代码,如果多个请求同时过来,
会报 java.nio.channels.ClosedChannelException: null at org.apache.hadoop.hdfs.ExceptionLastSeen.throwException4Close
网上居然很难找到正确答案,经过多次尝试,修改后,
public boolean uploadFile(MultipartFile file, String dst) {
try {
long start = System.currentTimeMillis();
// 创建Hadoop配置对象
Configuration config = new Configuration();
config.set("fs.defaultFS", hdfsUri);
Path dstPath = new Path(ROOT_PATH + dst);
FileSystem fs = dstPath.getFileSystem(config);
// 上传文件到HDFS
InputStream in = new BufferedInputStream(file.getInputStream());
OutputStream out = fs.create(dstPath);
IOUtils.copyBytes(in, out, 4096, true);
in.close();
// 关闭FileSystem对象
<font color="red">// fs.close();</font>
long end = System.currentTimeMillis();
logger.info("文件名称: {} 耗时: {}", dst, end - start);
return true;
} catch (Exception e) {
logger.error("文件:{}, 上传错误!, ", dst, e);
return false;
}
}
如上,不要执行fs.close();就好了。
原因:
经过查阅资料和查看源码,
FileSystem fs = dstPath.getFileSystem(config); 不是新建,而是从CACHE中拿。
所以多个请求关了同一个fs。
参考:
https://arganzheng.life/hadoop-filesystem-closed-exception.html