10: 自定义connector
背景:想用redis 维表join的功能,flink 本身没有redis connector, 找的第三方的实现(大数据羊说开源的),可以在IDE里成功运行,但是无法在SQL client里运行。
这里研究一下自定义connector.
首先了解一下java SPI: SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。
API (Application Programming Interface)在
大多数情况下,都是实现方
制定接口并完成对接口的实现,调用方
仅仅依赖接口调用,且无权选择不同实现。 从使用人员上来说,API 直接被应用开发人员使用。
SPI (Service Provider Interface)
是调用方
来制定接口规范,提供给外部来实现,调用方在调用时则
选择自己需要的外部实现。 从使用人员上来说,SPI 被框架扩展人员使用。
spi的一个demo:
定义接口:
public interface UploadCDN { void upload(String url); }
接口的两个实现:
public class QiyiCDN implements UploadCDN { //上传爱奇艺cdn @Override public void upload(String url) { System.out.println("upload to qiyi cdn"); } } public class ChinaNetCDN implements UploadCDN {//上传网宿cdn @Override public void upload(String url) { System.out.println("upload to chinaNet cdn"); } }
然后需要在resources目录下新建META-INF/services目录,并且在这个目录下新建一个与上述接口的全限定名一致的文件,在这个文件中写入接口的实现类的全限定名
这时,通过serviceLoader加载实现类并调用:
public static void main(String[] args) { ServiceLoader<UploadCDN> uploadCDN = ServiceLoader.load(UploadCDN.class); for (UploadCDN u : uploadCDN) { u.upload("filePath"); } }
下面看一下自定义connector:
Metadata:
DDL创建动态表(dynamicTable)的metadata,会生成CatalogTable的实例。
Planning:
在执行SQL语句的时候,将 上面的CatalogTable 解析为 DynamicTableSource(用于在 SELECT 查询中读取)和 DynamicTableSink(用于在 INSERT INTO 语句中写入)。DynamicTableSourceFactory 和 DynamicTableSinkFactory 将根据 CatalogTable 的元数据(Metadata)创建 DynamicTableSource 和 DynamicTableSink 的实例。工厂的目的是验证选项(例如示例中的 'port'')、配置编码/解码格式以及创建表连接器的参数化实例。
默认情况下,使用 Java 的服务提供者接口 (SPI) 发现 DynamicTableSourceFactory 和 DynamicTableSinkFactory 的实例。连接器选项(例如示例中的 'connector' = 'custom')必须对应于有效的工厂标识符。
DynamicTableSource 、 DynamicTableSink最终为读取/写入实际数据生成具体的运行时实现。
规划器使用源(source)和接收器(sink)实例来执行特定于连接器(connector)的双向通信,直到找到最佳逻辑计划。根据可选声明的能力接口(例如 SupportsProjectionPushDown 或 SupportsOverwrite),规划器可能会对实例应用更改,从而改变生成的运行时实现。
Runtime:
一旦逻辑规划完成,规划器将从表连接器connector获取运行时实现。运行时逻辑在 Flink 的核心连接器接口中实现,例如 InputFormat 或 SourceFunction。
这些接口按另一个抽象级别分组为 ScanRuntimeProvider、LookupRuntimeProvider 和 SinkRuntimeProvider 的子类。
例如,OutputFormatProvider(提供 org.apache.flink.api.common.io.OutputFormat)和 SinkFunctionProvider(提供 org.apache.flink.streaming.api.functions.sink.SinkFunction)都是 SinkRuntimeProvider 的具体实例,规划器可以 处理。
自定义 redis sink connector
- 自定义 Factory,根据需要实现 DynamicTableSourceFactory, DynamicTableSinkFactory.
- 自定义 TableSink, 实现 DynamicTableSink
- 定义 Options 也就是 connector 相关的属性
- 在 resource 下面添加配置文件 org.apache.flink.table.factories.Factory 里面添加 Factory 的全限定名
参考: Java SPI详解 - jy的blog - 博客园 (cnblogs.com)
https://blog.csdn.net/xianpanjia4616/article/details/117639507