# flink-sql-bootstrap **Repository Path**: tonyabasy/flink-sql-bootstrap ## Basic Information - **Project Name**: flink-sql-bootstrap - **Description**: A production-grade enhanced launcher for Flink SQL jobs — custom Catalog snapshots, Multi-Statement SQL Script deployment, and fine-grained per-operator resource tuning. - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: https://github.com/tonyabasy/flink-sql-bootstrap - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-06-03 - **Last Updated**: 2026-06-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

English | 中文

Flink SQL Bootstrap

可能你的 Flink SQL 生产级部署仅需要:一个 3M 的 JAR

License Java Flink

## 目录 - [为什么要用 Flink SQL Bootstrap](#为什么要用-flink-sql-bootstrap) - [核心能力](#核心能力) - [快速开始](#快速开始) - [环境要求](#环境要求) - [Step 1 — 运行 SQL 脚本](#step-1--运行-sql-脚本) - [Step 2 — 生成并注入资源配置](#step-2--生成并注入资源配置) - [Step 3 — 带 Catalog 快照部署](#step-3--带-catalog-快照部署) - [运行模式](#运行模式) - [配置参考](#配置参考) - [资源调优 JSON](#资源调优-json) - [Catalog 快照 JSON](#catalog-快照-json) - [能力边界](#能力边界) - [如何贡献](#如何贡献) - [文档](#文档) - [许可证](#许可证) ## 为什么要用 Flink SQL Bootstrap 原生 Flink SQL 在生产环境有三大痛点: | 痛点 | 原生 Flink SQL | Flink SQL Bootstrap | |-----------|------------------|---------------------| | **Catalog 不可复用** | DDL 与作业强耦合,每次提交都要重建表。 | 通过 **Catalog 快照 JSON** 部署 —— 表、视图、UDF 预注册,运行时无需 DDL。 | | **不支持多语句脚本** | 原生仅支持单条语句提交。 | 完整的 **Multi-Statement SQL Script** 支持 —— DDL 立即执行,DML 编译优化后作为单一 Pipeline 提交。 | | **资源调优粒度粗** | 仅支持 TM/JM 级别的粗粒度配置(内存、slot)。 | **算子级资源注入** —— 为每个算子独立配置 CPU、堆内存、托管内存、并行度和链策略。 | ## 核心能力 1. **自定义 Catalog 快照** —— 将表、视图和 UDF 序列化为 JSON 文件。作业启动时 Catalog 已就绪,SQL 脚本中无需写 DDL。支持多协议快照加载,为**实时数仓元数据管理**提供遍历。 2. **Multi-Statement SQL Script** —— 在单个 `.sql` 文件中编写 `CREATE TABLE`、`SET`、`INSERT`、`CALL` 等语句。启动器自动切分、校验并编排执行。 3. **细粒度资源调优** —— 通过 `--init-resource` 生成资源模板,按算子调整并行度和资源,并在作业提交前注入 Flink DAG。 4. **多协议资源加载** —— 支持从 `classpath:`、`file://`、`http(s)://`、`hdfs://`、`s3://` 加载 SQL 脚本、Catalog 快照、细粒度资源配置。 5. **支持所有 Flink 部署模式** —— 支持 Standalone、Per-Job、Application、Session 模式,以及 Local、YARN、Kubernetes 等资源环境。 6. **SQL 语法校验与行级错误定位** —— 通过 `--validate` 在本地快速校验 SQL 语法,无需提交到 Flink 集群。错误信息精确到行号和列号,便于快速迭代。 7. **Flink 1.20+ 兼容** —— 适配 Flink 1.20 及以后版本,不修改 Flink 引擎或 Planner。(未来会持续适配更多版本) ## Flink 版本兼容性 通过[兼容性测试套件](docs/flink-compat-test_CN.md)在 Local、YARN(docker-compose)、Kubernetes(kind)环境下全面验证。所有模式均使用 UDF 依赖、Catalog 快照和资源调优配置进行测试。 | Flink 版本 | Local | YARN-App | YARN-Session | K8s-Session | K8s-App | |-----------|:-----:|:--------:|:------------:|:-----------:|:-------:| | 1.20.4 | ✅ | ✅ | ✅ | ✅ | ✅ | | 2.0.2 | ✅ | ✅ | ✅ | ✅ | ✅ | | 2.1.1 | ✅ | ✅ | ✅ | ✅ | ✅ | | 2.2.0 | ✅ | ✅ | ✅ | ✅ | ✅ | - **✅ 通过** —— JAR 成功提交并执行。 - **❌ 失败** —— API 不兼容导致作业提交或执行失败。 - **—** —— 尚未测试(NT)。 完整报告:[docs/flink-compat-test-1.0.1.html](https://tonyabasy.github.io/flink-sql-bootstrap/flink-compat-test-1.0.1.html) ## 快速开始 ### 环境要求 | 依赖 | 版本 | |------|------| | Java | 11+ | | Flink | 1.20+ | > **前置准备**:本项目依赖 `flink-sql-gateway-*.jar`,运行前需要将其从 `$FLINK_HOME/opt` 复制到 `$FLINK_HOME/lib`: > > ```bash > cp $FLINK_HOME/opt/flink-sql-gateway-*.jar $FLINK_HOME/lib > ``` ### 下载 从 [GitHub Releases](https://github.com/tonyabasy/flink-sql-bootstrap/releases) 下载最新 JAR。 ### Step 1 — 运行 SQL 脚本 最简单的方式 —— 直接提交一条 SQL 脚本: ```bash $FLINK_HOME/bin/flink run \ --target local \ flink-sql-bootstrap-${version}.jar \ --script-file classpath:example-word-count.sql ``` 其中 `example-word-count.sql` 包含 **DDL + DML**,无需任何外部依赖: ```sql -- datagen 自动生成句子 → 分词 → 分组计数 → print 输出 CREATE TEMPORARY TABLE source_table ( sentence STRING ) WITH ( 'connector' = 'datagen', 'rows-per-second' = '1' ); CREATE TEMPORARY TABLE sink_table ( word STRING, cnt BIGINT ) WITH ( 'connector' = 'print' ); INSERT INTO sink_table SELECT word, COUNT(*) AS cnt FROM source_table CROSS JOIN UNNEST(SPLIT(sentence, ' ')) AS t(word) GROUP BY word; ``` 执行后将在控制台看到类似输出(实际值可能是随机字符串,因为 datagen 生成随机数据): ``` Flink SQL> INSERT INTO sink_table SELECT word, COUNT(*) AS cnt ... > +I[, 1] > +I[, 1] > +I[, 1] ``` ### Step 2 — 生成并注入资源配置 从 SQL 脚本生成资源模板: ```bash $FLINK_HOME/bin/flink run \ --target local \ flink-sql-bootstrap-${version}.jar \ --script-file classpath:example-word-count.sql \ --init-resource ``` 输出示例: ```json { "version" : 1, "operators" : [ { "uid" : "1_source", "name" : "source_table[1]", "parallelism" : 1, "chainStrategy" : "HEAD" }, { "uid" : "2_correlate", "name" : "Correlate[2]", "parallelism" : 1, "chainStrategy" : "ALWAYS" }, { "uid" : "3_calc", "name" : "Calc[3]", "parallelism" : 1, "chainStrategy" : "ALWAYS" }, { "uid" : "5_group-aggregate", "name" : "GroupAggregate[5]", "parallelism" : -1, "chainStrategy" : "ALWAYS" }, { "uid" : "6_sink", "name" : "sink_table[6]", "parallelism" : -1, "chainStrategy" : "ALWAYS" } ] } ``` 生成的模板为每个算子分配了 `uid`、`name`、默认 `parallelism` 和 `chainStrategy`。修改这些字段可调整并行度和链策略,然后添加 `resource` 字段配置 CPU/内存(支持的字段见[资源调优 JSON](#资源调优-json))。 将输出保存为 `resource.json`,修改参数后带资源配置提交: ```bash $FLINK_HOME/bin/flink run \ --target local \ flink-sql-bootstrap-${version}.jar \ --script-file classpath:example-word-count.sql \ --resource-file classpath:resource.json ``` ### Step 3 — 带 Catalog 快照部署 通过 Catalog 快照预注册表和 UDF,使 SQL 脚本中 **不写任何 DDL**。需要配合专门的 SQL 脚本使用: ```bash $FLINK_HOME/bin/flink run \ --target local \ flink-sql-bootstrap-${version}.jar \ --script-file classpath:example-word-count-advanced.sql \ --catalog-file classpath:example-catalog.json \ --resource-file classpath:example-resource.json \ --dependency classpath:example-udf-reverse.jar \ --dependency classpath:example-udf-substring.jar ``` 其中 `example-word-count-advanced.sql` 只包含 DML(表和 UDF 已由 Catalog 快照预注册): ```sql INSERT INTO dws_word_count SELECT my_reverse(my_substring(word, 0, 2)) AS word, COUNT(*) AS cnt FROM ods_words CROSS JOIN UNNEST(SPLIT(sentence, ' ')) AS t(word) GROUP BY my_reverse(my_substring(word, 0, 2)); ``` 输出(注意 2 字符前缀 —— `my_reverse(my_substring(...))` UDF 已生效): ``` Job has been submitted with JobID +I[6a, 1] +I[00, 1] +I[a3, 1] +I[8f, 1] ``` ## 运行模式 除了完整执行外,还提供三种干运行模式,适用于 CI/CD 和开发调试: | 模式 | 参数 | 说明 | |------|------|------| | **语法校验** | `--validate` | 解析并校验 SQL 语法,不编译也不执行。 | | **编译** | `--compile` | 解析、校验并编译 SQL 脚本,输出优化后的执行计划 JSON。 | | **生成资源模板** | `--init-resource` | 翻译 SQL 计划并输出资源配置模板,供用户调优。 | ```bash # 校验 SQL 语法 $FLINK_HOME/bin/flink run ... --script-file job.sql --validate # 编译并查看执行计划 $FLINK_HOME/bin/flink run ... --script-file job.sql --compile # 生成资源模板 $FLINK_HOME/bin/flink run ... --script-file job.sql --init-resource ``` ## 配置参考 ### 资源调优 JSON 描述每个算子的资源配置。每个算子通过 `uid`(优先)或 `name` 匹配。 ```json { "version": 1, "defaultParallelism": 2, "operators": [ { "uid": "1_source", "name": "ods_words[1]", "parallelism": 1, "chainStrategy": "HEAD", "resource": { "profile": "stateless" } }, { "uid": "5_group-aggregate", "name": "GroupAggregate[5]", "parallelism": 4, "chainStrategy": "ALWAYS", "resource": { "cpu": 1.0, "heap": "2048m", "managed": "256m" } } ] } ``` **字段说明:** | 字段 | 类型 | 说明 | |-------|------|-------------| | `version` | int | 配置格式版本,当前为 `1`。 | | `defaultParallelism` | int | 全局默认并行度,`0` 表示不覆盖。 | | `operators` | 数组 | 算子配置列表。 | | `operators[].uid` | string | 稳定 UID,用于精确匹配。会覆盖 Flink 自动生成的 UID。 | | `operators[].name` | string | 算子名称,作为 UID 匹配的兜底策略。 | | `operators[].parallelism` | int | 算子并行度,`-1` 表示使用 Flink 默认。 | | `operators[].chainStrategy` | string | `HEAD`、`ALWAYS` 或 `NEVER`,控制算子链合并策略。 | | `operators[].resource.profile` | string | 预置规格:`stateless`、`stateful`、`join_heavy`、`sink`。 | | `operators[].resource.cpu` | double | CPU 核数(支持小数)。 | | `operators[].resource.heap` | string | Task 堆内存,如 `"512 MB"`、`"2g"`。 | | `operators[].resource.managed` | string | 托管内存,如 `"256m"`。 | ### Catalog 快照 JSON 描述一个自包含的 Catalog,包含表、视图和 UDF。支持计算列、主键、Watermark、分区键和 metadata 列。 ```json { "version": 1, "snapshotId": "example-word-count", "catalogName": "platform", "databaseName": "default", "tables": [ { "database": "default", "name": "ods_words", "columns": [ { "name": "sentence", "type": "STRING", "nullable": true }, { "name": "ts", "type": "TIMESTAMP_LTZ(3)", "nullable": false, "isComputed": true, "computedExpr": "PROCTIME()" } ], "primaryKey": { "columnNames": ["id"], "enforced": true }, "watermark": { "rowtimeColumn": "ts", "expression": "ts - INTERVAL '5' SECOND" }, "options": { "connector": "datagen", "rows-per-second": "1" } } ], "views": [ { "database": "default", "name": "v_latest_words", "expandedQuery": "SELECT sentence FROM ods_words WHERE ts > CURRENT_TIMESTAMP - INTERVAL '10' MINUTE" } ], "udfs": [ { "database": "default", "name": "my_reverse", "kind": "SCALAR", "className": "examples.udf.MyReverseFunction", "functionLanguage": "JAVA", "jarRef": "example-udf-reverse.jar" } ] } ``` > **注意**:UDF 的 `jarRef` 仅用于血缘统计。UDF JAR 的真实加载通过 `--dependency` 或 `pipeline.classpaths` 完成,不会根据此字段自动加载。 ## 能力边界 **它是什么:** - 一个生产级的 Flink SQL Application 模板。 - 一座桥梁,连接 Flink SQL 脚本与外部元数据及细粒度资源控制。 **它不是什么:** - **不是** Flink SQL Gateway —— 遵循 `flink run` 作业提交范式,而非交互式 Gateway 模式。 - **不是** 工具类库 —— 它是一个带 `main()` 方法的**应用模板**,不是一个引入依赖即可使用的工具包。 **边界承诺:** - 零修改 Flink 引擎、Planner 或 SQL 语义。 - 不提供任何自定义 SQL 方言 —— 执行结果与原生 Flink SQL 完全一致。 - 用户配置的 Flink 参数原样透传,不做任何改动。 ## 许可证 基于 Apache License, Version 2.0 开源。 详见 [LICENSE](LICENSE)。