Java操作hdfs,总是报ClosedChannelException

现象

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值