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:
定义接口:
1 2 3 | public interface UploadCDN { void upload(String url); } |
接口的两个实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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加载实现类并调用:
1 2 3 4 5 6 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2018-01-20 @JsonProperty 注解
2018-01-20 bean validator - Hibernate validator
2018-01-20 java注解的基本知识
2018-01-20 JWT(JSON WEB TOKEN) / oauth2 / SSL
2018-01-20 Guice 学习