flink canal-format 解析多表binlog的bug解决方案
版本flink1.12.0
基于flink1.13 master版本进行修改编译 因为1.13 尚未正式发布
前置问题
在使用时候 配置’canal-json.table.include’ 并不能正确的过滤掉指定表的binlog ,在解析那步会报错,比如 我想读取 canal-json.table.include = ‘a’ 表的binlog,a表有一个source字段为int类型, 但是这个时候如果b表也有source字段,但是source字段是string类型,这个时候b的source存了一个非int的数据,这个时候会报错。
向flink社区提交的issues
https://issues.apache.org/jira/browse/FLINK-20385%3E
https://issues.apache.org/jira/browse/FLINK-20385
1 功能点 : 支持canal-json.database.include 正则匹配
2 解决 :多表binlog导致的报错
3 解决:解决ddl binlog报错
具体代码修改
1 修改 flink-json包的CanalJsonDeserializationSchema.deserialize()方法
@Override
public void deserialize(byte[] message, Collector<RowData> out) throws IOException {
try {
//先解析出json 防止走下一步报错
final JsonNode root = jsonDeserializer.deserializeJsonNode(message);
//这里使用java正则表达 来做通配功能
if (this.table != null) {
if (!Pattern.matches(this.table, String.valueOf(root.get("table")))) {
return;
}
}
//这里过滤掉isDdl:true的binlog
String isDdl = String.valueOf(root.get("isDdl"));
if (StringUtils.isBlank(isDdl)) {
if ("true".equals(isDdl)) {
return;
}
}
//因为不需要去做匹配database 所以这里没有去做
if (database != null) {
if (!database.equals(String.valueOf(root.get("database")))) {
return;
}
}
//在这一步 才去调用转换为flink RowData 防止因为数据类型导致的错误
GenericRowData row = (GenericRowData) jsonDeserializer.deserializeRowData(root);
String type = row.getString(2).toString(); // "type" field
2 添加flink-json包JsonRowDataDeserializationSchema 2个方法
/**
* 先解析获取json对象
* @param message
* @return
* @throws IOException
*/
public JsonNode deserializeJsonNode(byte[] message) throws IOException {
try {
final JsonNode root = objectMapper.readTree(message);
return root;
} catch (Throwable t) {
if (ignoreParseErrors) {
return null;
}
throw new IOException(
format("Failed to deserialize JsonNode '%s'.", message), t);
}
}
/**
* 然后再映射成RowData对象
* @param message
* @return
* @throws IOException
*/
public RowData deserializeRowData(JsonNode message) throws IOException {
try {
return (RowData) runtimeConverter.convert(message);
} catch (Throwable t) {
if (ignoreParseErrors) {
return null;
}
throw new IOException(
format("Failed to deserialize RowData '%s'.", message), t);
}
}
3 编译修改的代码,替换你本地flink lib下的flink-json包
如果本地idea运行 需要去掉pom.xml的flink-json依赖,并且把编译的flink-json包添加到你的idea 项目libraries。