背景
使用flink sql读取某个目录的文件, 目录下存在某个文件副本丢失或block丢失, 但是任务无法正常运行, 直接异常退出了. 想在代码层面进行控制, 损坏的文件进行读取失败时不抛出异常, flink sql的封装太多, 无法对某个过程做筛选操作, 根据官网的提示, 可以通过创建META-INF/services/org.apache.flink.core.fs.FileSystemFactory
文件, 来替换掉原来的FileSystemFactory
, 做一些自定义的操作
pom
org.apache.flink
flink-table-planner-blink_2.12
1.13.1
org.apache.flink
flink-clients_2.12
1.13.1
测试示例
测试中的示例为副本丢失的文件, 可在hdfs的web界面查看
public class ReadHdfsSqlTest {
public static void main(String[] args) {
String table = "tmp_table";
String schema = "message STRING";
//可以是目录,也可以是文件
String path = "hdfs://192.168.0.1:8020/user/flink/ha/application_1632893476013_0162/completedCheckpoint24e63d0c5530";
String createSql = String.format("CREATE TABLE %s( %s ) WITH ('connector'='filesystem','path'='%s','format'='raw')",
table, schema, path);
TableEnvironment env = TableEnvironment.create(EnvironmentSettings.newInstance().inBatchMode().build());
env.executeSql(createSql).print();
env.executeSql("select * from " + table + " limit 10").print();
}
}
如果不进行改造, 程序会异常退出, 无法进行后续文件的读取处理
自定义FileSystemFactory
通过源码跟踪, 需要把原有的三个hadoop类复制过来进行简单改造, 随后在META-INF
下创建下图的文件
org.apache.flink.runtime.fs.hdfs.HadoopDataInputStream
两个read()方法进行异常捕获, 报错期间会有多个WARN的打印(无影响), 最后才会抛出异常进入到catch代码块
org.apache.flink.runtime.fs.hdfs.HadoopFileSystem
更改两个open()方法的返回值
org.apache.flink.runtime.fs.hdfs.HadoopFsFactory
更改getSchema()的返回值为hdfs
@Override
public String getScheme() {
// the hadoop factory creates various schemes
return "hdfs";
}
create()方法中创建自定义的HadoopFileSystem