Flink DataStream readFile中FilePathFilter存在的坑

说明

最近有需求需要实时监控HDFS指定目录,然后对新增文件的每一行进行处理。

采用了Flink DataStream API的readFile方法来实现。

文件都是.gz结尾的,也会存在脏文件进来,所以需要对文件名进行过滤,于是就用FilePathFilter

在不过滤之前,可以正常监听目录;但是加了过滤后就不能监听了。

纳闷了好一会,后来点进去仔细看了看源码,才发现是使用FilePathFilter的姿势有问题。


这里的FilePathFilter居然是用来过滤目录的。。。实现代码如下:

代码摘自org.apache.flink.streaming.api.functions.source.ContinuousFileMonitoringFunction

	private Map<Path, FileStatus> listEligibleFiles(FileSystem fileSystem, Path path) throws IOException {

		final FileStatus[] statuses;
		try {
            // 列出目录下的所有文件状态
			statuses = fileSystem.listStatus(path);
		} catch (IOException e) {
		}

		if (statuses == null) {
			。。。。
		} else {
			Map<Path, FileStatus> files = new HashMap<>();
			// 处理新文件
			for (FileStatus status : statuses) {
                // 如果不是目录
				if (!status.isDir()) {
					Path filePath = status.getPath();
					long modificationTime = status.getModificationTime();
                    // 看他的修改时间是否应该被忽略
					if (!shouldIgnore(filePath, modificationTime)) {
						files.put(filePath, status);
					}
                // 如果是目录。先判断是否开启了递归扫描;
                // 再判断目录是否应该被接收。其中就是去用`FilePathFilter`来过滤的
				} else if (format.getNestedFileEnumeration() && format.acceptFile(status)){
					files.putAll(listEligibleFiles(fileSystem, status.getPath()));
				}
			}
			return files;
		}
	}

	// 上面用到的acceptFile方法
	public boolean acceptFile(FileStatus fileStatus) {
		final String name = fileStatus.getPath().getName();
		return !name.startsWith("_")
			&& !name.startsWith(".")
			&& !filesFilter.filterPath(fileStatus.getPath());
	}

源码中FilePathFilter类的filterPath中也确实写了是过滤目录的:

// org.apache.flink.api.common.io.FilePathFilter
// 如果在处理目录时,需要忽略给定的filePath,则返回true
public abstract boolean filterPath(Path filePath);

所以是不支持过滤文件名的,只支持过滤目录名。

我最开始是过滤了.gz结尾的,由于没有一个目录是以.gz结尾的,导致一个文件都扫描不到。。。

总结

  • Flink实时监控目录下的文件,官方提供的Source不支持过滤文件名,需要我们自己实现
  • Flink监控文件这块比Spark鸡肋很多,Spark Streaming这块实现还不错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值