流计算连接器 SQL 使用说明

更新时间:
复制 MD 格式

流计算 SQL 通过连接器(Connector)对接上下游数据系统,既可以把消息队列中的消息读入作业,也可以把作业结果写回消息队列。本文说明 Kafka、MQTT、RocketMQ 连接器的 DDL 建表语法与 WITH 参数,覆盖 Source 和 Sink 两端的必填项、默认值、取值约束与可用元数据列,可据此补全建表语句。

每个连接器均可作为 Source(数据源,读取消息)或 Sink(数据汇,写入消息)使用。在流计算控制台的连接器页面,单击作为 Source 创建或作为 Sink 创建可快速生成建表模板,再参照本文补全参数。

连接器范围与选型

按对接的消息队列产品与消息类型选择连接器:

连接器适用场景SourceSink
Kafka读写云消息队列 Kafka 版的 Topic,需利用时间戳、分区、offset 等元数据。支持支持
MQTT物联网(IoT)设备上下行消息的读取与写入。支持支持
RocketMQ读写云消息队列 RocketMQ 版的普通消息,需按 Tag、Key、Queue 等属性过滤或路由。支持支持
说明

支持的连接器会陆续开放,如有紧急需求,请提交工单。

通用建表规则

所有连接器统一采用标准 CREATE TABLE 语法定义表结构,连接器之间的差异集中在 WITH 子句的参数上:

CREATE TABLE table_name (
  -- 字段定义
  col1 STRING,
  col2 BIGINT,
  ...
) WITH (
  'connector' = '<连接器类型>',
  -- 连接器专属参数
  ...
);

下文参数表中,“是否必填”列标记为“是”的参数在建表时必须提供;标记为“否”的参数可省略,省略时采用“默认值”列所示的取值;标记为“条件必填”的参数是否必须提供取决于其他参数的取值,具体条件见“说明”列。

参数命名与取值风格不跨连接器通用。Kafka 与 MQTT 的参数不带前缀(如 scan.startup.mode、sink.delivery-guarantee),RocketMQ 的参数统一以 rocketmq. 为前缀;同名或同义参数的取值集也各不相同,例如“消费组已提交位点”,Kafka 写作 group-offsets,MQTT 写作 committed;“至少一次投递”,MQTT 写作 at-least-once,RocketMQ 写作 AT_LEAST_ONCE。配置时以对应连接器章节列出的取值集为准,不要跨连接器复用取值。

示例中的 ${secret_ak} 与 ${secret_sk} 为占位符,分别对应 AccessKey ID 与 AccessKey Secret,建表时需替换为实际取值。

Kafka 连接器

Kafka 连接器用于对接云消息队列 Kafka 版的 Topic,支持读取和写入消息,并可利用消息的时间戳、分区、offset 等元数据。

作为 Source

配置前需确认以下约束:

  • topic 与 topic-pattern 二选一,不可同时配置。

  • scan.startup.mode 为 specific-offsets 时需指定 scan.startup.specific-offsets,为 timestamp 时需指定 scan.startup.timestamp-millis。

  • 使用 key.format 时需同时指定 key.fields。

CREATE TABLE kafka_source (
  `user_id` BIGINT,
  `item_id` BIGINT,
  `behavior` STRING,
  -- 元数据字段(可选)
  `ts` TIMESTAMP(3) METADATA FROM 'timestamp',
  `partition_id` BIGINT METADATA FROM 'partition' VIRTUAL,
  `offset` BIGINT METADATA FROM 'offset' VIRTUAL
) WITH (
  'connector' = 'kafka',
  'topic' = 'your_topic',
  'properties.bootstrap.servers' = 'alikafka-xxx:9092',
  'properties.group.id' = 'your_consumer_group',
  'scan.startup.mode' = 'group-offsets',
  'format' = 'json'
);

Source 参数说明:

参数是否必填默认值说明
connector是无固定填 kafka。
topic是无读取的 Topic 名称。多个 Topic 用分号分隔,如 topic-1;topic-2。
topic-pattern否无以正则匹配一批 Topic,与 topic 二选一。
properties.bootstrap.servers是无Kafka 接入点地址,多个用逗号分隔。可在实例详情页获取。
properties.group.id是无消费组 ID,用于记录消费位点。
scan.startup.mode否group-offsets启动消费位点:earliest-offset(最早)/latest-offset(最新)/group-offsets(消费组已提交位点)/timestamp(指定时间)/specific-offsets(指定 offset)。
scan.startup.specific-offsets否无当模式为 specific-offsets 时指定,格式 partition:0,offset:42;partition:1,offset:300。
scan.startup.timestamp-millis否无当模式为 timestamp 时指定,起始时间的毫秒时间戳。
format / value.format是无消息体解析格式,如 json、csv、avro。
key.format否无消息 Key 的解析格式,需配合 key.fields 使用。
key.fields否无指定哪些字段来自消息 Key。
properties.*否无透传给 Kafka 客户端的原生参数,如 properties.security.protocol。
scan.topic-partition-discovery.interval否无动态分区发现间隔,如 10s,用于自动感知 Topic 扩容。

作为 Sink

sink.delivery-guarantee 为 exactly-once 时需配合事务,并通过 sink.transactional-id-prefix 指定唯一的事务 ID 前缀。

CREATE TABLE kafka_sink (
  `user_id` BIGINT,
  `item_id` BIGINT,
  `behavior` STRING
) WITH (
  'connector' = 'kafka',
  'topic' = 'your_sink_topic',
  'properties.bootstrap.servers' = 'alikafka-xxx:9092',
  'format' = 'json',
  'sink.partitioner' = 'default'
);

Sink 参数说明:

参数是否必填默认值说明
connector是无固定填 kafka。
topic是无写入的目标 Topic。
properties.bootstrap.servers是无Kafka 接入点地址。
format / value.format是无消息体序列化格式。
key.format否无Key 的序列化格式,配合 key.fields。
key.fields否无指定作为消息 Key 写入的字段。
sink.partitioner否default分区策略:default(Kafka 默认)/fixed(每个并行度固定写入对应分区)/round-robin(轮询)/自定义分区器类名。
sink.delivery-guarantee否at-least-once投递语义:none/at-least-once/exactly-once(需配合事务)。
sink.transactional-id-prefix否无exactly-once 语义下的事务 ID 前缀,必须唯一。
properties.*否无透传给 Kafka Producer 的原生参数。

数据格式(Format 常用参数)

Kafka Source 和 Sink 均通过 format 或 value.format 指定消息体的数据格式:Source 将消息体反序列化为表中的字段,Sink 将表中的字段序列化为消息体。常用取值包括 json、csv、avro、raw、debezium-json 和 canal-json。不同格式有各自的附加参数,按 格式名.参数 的形式配置到 WITH 子句,例如 json.ignore-parse-errors。

JSON 格式通过 'format' = 'json' 或 'value.format' = 'json' 指定,附加参数如下:

参数适用端默认值说明
json.ignore-parse-errorsSourcefalse是否忽略解析错误。开启后,存在解析错误的记录会被跳过,或将异常字段置为 NULL。
json.fail-on-missing-fieldSourcefalse缺少字段时是否报错;默认将缺失字段置为 NULL。
json.timestamp-format.standardSource/SinkSQL读取和写入时使用的时间戳格式,可选 SQL 或 ISO-8601。

CSV 格式通过 'format' = 'csv' 或 'value.format' = 'csv' 指定,附加参数如下:

参数适用端默认值说明
csv.field-delimiterSource/Sink,字段分隔符。
csv.ignore-parse-errorsSourcefalse是否忽略解析错误。开启后,存在解析错误的记录会被跳过,或将异常字段置为 NULL。
csv.null-literalSource/Sink无用于表示 NULL 的字符串,读取时识别为 NULL,写入时用于输出 NULL 值。

以下格式均支持 Source 和 Sink:

  • raw:原始消息体格式,适合单字段读取和写入。

  • avro:Avro 二进制格式。

  • debezium-json/canal-json:用于读取或输出 CDC 变更消息。

MQTT 连接器

MQTT 连接器支持读取和写入 MQTT 消息,适用于物联网(IoT)设备上下行消息场景。

作为 Source

配置前需确认以下约束:

  • source.type 决定必填项:topic 模式需指定 topic 且禁用 group-id,status 模式需指定 group-id 且禁用 topic。

  • Source 的 topic 仅支持一个一级 Topic,不支持多级路径及 +、# 通配符。

  • 未配置 consumer-group 时,source.commit-offsets-on-checkpoint 不能设为 true;scan.startup.mode 与 scan.new-partition.startup.mode 取 committed 也需先配置 consumer-group。

  • source.empty-pull-backoff.max 不能小于 source.empty-pull-backoff.initial。

CREATE TABLE mqtt_source (
  `user_id` STRING,
  `user_name` STRING,
  `action` STRING,
  `event_time` TIMESTAMP(3),
  -- 元数据字段(可选)
  `mqtt_client_id` STRING METADATA VIRTUAL,
  `mqtt_qos_level` STRING METADATA VIRTUAL,
  `mqtt_real_topic` STRING METADATA VIRTUAL
) WITH (
  'connector' = 'mqtt',
  'topic' = 'stream-source-1',
  'instance-id' = 'mqtt-cn-xxxxxxxxx',
  'endpoints' = 'mqtt-cn-xxxxxxxxx-single-internal-vpc.mqtt.aliyuncs.com:5673',
  'access-key' = '${secret_ak}',
  'secret-key' = '${secret_sk}',
  'scan.startup.mode' = 'latest',
  'source.pull.batch-size' = '32',
  'source.pull.interval' = '100 ms',
  'source.pull.suspend-timeout' = '30 s',
  'message.field-delimiter' = ';'
);

Source 参数说明:

参数是否必填默认值说明
connector是无固定填 mqtt。
instance-id是无MQTT 实例 ID,如 mqtt-cn-xxxxxxxxx。
endpoints是无MQTT 实例的流计算内网接入地址及端口,格式见示例。
access-key是无用于鉴权的 AccessKey ID。
secret-key是无用于鉴权的 AccessKey Secret。
source.type否topictopic 读取指定一级 Topic 下的消息;status 读取指定设备 Group 的上下线事件。
topic条件必填无topic 模式必填,指定一个一级 Topic,不支持多级路径及 +、# 通配符;status 模式禁用。
group-id条件必填无status 模式必填,指定 MQTT 设备 Group;topic 模式禁用。
consumer-group否无服务端消费位点管理组,与设备 group-id 用途不同。不填时使用匿名身份,不查询或提交服务端位点。
source.commit-offsets-on-checkpoint否配置 consumer-group 时为 true,否则为 false是否在数据处理完成后提交服务端消费位点;未配置 consumer-group 时不能设为 true。
scan.startup.mode否latestearliest:最早可用位点;latest:最新位点;committed:已提交位点,需配置 consumer-group。
scan.new-partition.startup.mode否earliest首次发现后新增队列的起始位点:earliest:最早可用位点;latest:最新位点;committed:已提交位点,需配置 consumer-group。
source.pull.batch-size否32单次拉取请求的最大消息条数,必须大于 0。
source.pull.callback.threads否4每个 Source Reader 的客户端回调线程数,必须大于 0;不限制并发拉取请求数。
source.pull.max-buffered-records否4096每个 Source Reader 的预取记录缓冲上限,必须大于 0。
source.pull.max-records-per-fetch否1024单次从预取缓冲返回的最大记录数,必须大于 0。
source.pull.interval否100 ms一次读取无数据后的等待时间,允许 0 ms。
source.pull.suspend-timeout否30 s服务端长轮询挂起超时,必须大于 0 ms。
source.empty-pull-backoff.enabled否true是否按队列启用空拉取指数退避。连续无消息且位点未推进时延长等待,有消息或位点推进后重置。
source.empty-pull-backoff.initial否100 ms初始退避等待时间,必须非负;0 ms 不增加退避等待。
source.empty-pull-backoff.max否5 s最大退避等待时间,不能小于 source.empty-pull-backoff.initial。
source.partition-discovery.interval否10 s新增消息队列的发现间隔;0 ms 关闭周期发现。
source.watermark.idle-timeout否继承全局配置,否则 1 minSQL 水位线下推时的空闲检测超时;0 ms 关闭检测。全局配置为 table.exec.source.idle-timeout。
message.encoding否UTF-8将消息体字节解码为文本的字符集,须与发送端一致。
message.field-delimiter否\u0001按物理列顺序拆分消息体的字段分隔符,示例使用 ;,支持 \t、\u0001 等转义写法。
message.line-delimiter否\n消息内多行记录的分隔符;单个 STRING 物理列不按行拆分。
message.length-check否nonenone:缺字段或解析失败跳行,多字段截断;skip:异常跳行;pad:缺字段补空、多字段截断,解析失败跳行;exception:抛错;skip-silent:静默跳行。

MQTT 可用元数据列:

Source 使用 METADATA FROM '<元数据名称>' VIRTUAL;列名与元数据名称一致时可省略 FROM。元数据不参与消息体编解码。

元数据类型读/写说明
topicSTRING NOT NULL读Source 读取的物理 Topic,如 <instance-id>%orders;完整 MQTT Topic 使用 mqtt_real_topic。
msg_idSTRING读服务端返回的消息 ID。
store_timestampBIGINT读消息的服务端存储时间,毫秒级 Unix 时间戳。
born_timestampBIGINT读消息携带的创建时间,毫秒级 Unix 时间戳。
mqtt_client_idSTRING读消息携带的 MQTT 客户端 ID。
mqtt_qos_levelSTRING读消息携带的 QoS 等级,以字符串返回。
mqtt_real_topicSTRING读完整 MQTT Topic,可用于 SQL 过滤。

作为 Sink

topic 需为完整的 MQTT 发布 Topic,不支持 +、# 通配符或空层级(如 /a、a/、a//b)。

CREATE TABLE mqtt_sink (
  `user_id` STRING,
  `user_name` STRING,
  `action` STRING
) WITH (
  'connector' = 'mqtt',
  'topic' = 'stream-sink-1/C',
  'instance-id' = 'mqtt-cn-xxxxxxxxx',
  'endpoints' = 'mqtt-cn-xxxxxxxxx-single-internal-vpc.mqtt.aliyuncs.com:5673',
  'access-key' = '${secret_ak}',
  'secret-key' = '${secret_sk}',
  'sink.delivery-guarantee' = 'at-least-once',
  'message.field-delimiter' = ';'
);

Sink 参数说明:

参数是否必填默认值说明
connector是无固定填 mqtt。
topic是无完整 MQTT 发布 Topic,如 stream-sink-1/C,其中 /C 是路径的一部分。不支持 +、# 通配符或空层级(如 /a、a/、a//b)。
instance-id是无MQTT 实例 ID。
endpoints是无MQTT 实例的流计算内网接入地址及端口,格式见示例。
access-key是无用于鉴权的 AccessKey ID。
secret-key是无用于鉴权的 AccessKey Secret。
sink.delivery-guarantee否at-least-onceat-least-once:至少一次投递,故障恢复可能重复;none:不提供投递保证,故障可能丢失或重复消息。
message.encoding否UTF-8将消息体文本编码为字节的字符集,消费端需使用相同字符集解码。
message.field-delimiter否\u0001按物理列顺序拼接消息体的字段分隔符,示例使用 ;。
sink.compression.threshold否4096序列化后的消息体达到该字节数时,默认采用 zlib(DEFLATE)尝试压缩;0 关闭压缩,不能为负数。
sink.max-pending-sends否2048每个 Sink Writer 尚未完成的异步发送数量上限,必须大于 0。
sink.io-threads否4每个 Sink Writer 的发送 I/O 线程数,必须大于 0。
sink.send-timeout否5 s单次发送调用的超时,须大于 0 ms,不限制多轮重试的总耗时。
sink.retry.max-retries否17连接器层的额外重试次数;0 关闭连接器层重试,客户端内部仍可能重试。
sink.retry.backoff否5 s连接器层重试的固定等待时间,允许 0 ms,不能为负数。

RocketMQ 连接器

RocketMQ 连接器用于对接云消息队列 RocketMQ 版,支持普通消息的读写,并可利用 Tag、Key、Queue 等属性过滤和路由消息。所有参数均以 rocketmq. 为前缀,分为三类:rocketmq.client.*(连接与消息编解码,Source/Sink 通用)、rocketmq.source.*(消费端专属)、rocketmq.sink.*(生产端专属)。

Source 与 Sink 共用的连接参数需满足以下约束:

  • 使用 4.x 独享实例,或 Topic、Group 需按实例隔离时,需指定 rocketmq.client.namespace。

  • 开启 ACL 鉴权的实例需指定 rocketmq.client.accessKey 与 rocketmq.client.secretKey;AccessKey Secret 严禁明文写入,建议使用密钥管理引用。

作为 Source

rocketmq.source.group 需在控制台预先创建。

CREATE TABLE rocketmq_source (
  `user_id` STRING,
  `user_name` STRING,
  `action` STRING,
  `event_time` TIMESTAMP(3),
  `topic` STRING METADATA VIRTUAL,
  `msg_id` STRING METADATA VIRTUAL,
  `store_timestamp` BIGINT METADATA VIRTUAL,
  `born_timestamp` BIGINT METADATA VIRTUAL,
  `queue_id` INT METADATA VIRTUAL,
  `queue_offset` BIGINT METADATA VIRTUAL,
  `keys` STRING METADATA VIRTUAL,
  `tags` STRING METADATA VIRTUAL
) WITH (
  'connector' = 'rocketmq',
  'rocketmq.source.topic' = 'source',
  'rocketmq.source.group' = 'GID-flink',
  'rocketmq.client.endpoints' = 'rmq-cn-xxx-vpc.cn-hangzhou.rmq.aliyuncs.com:8080',
  -- 4.x 独享实例需带 namespace(实例 ID):
  -- 'rocketmq.client.namespace' = 'MQ_INST_xxxxxxxx',
  'rocketmq.client.accessKey' = '${secret_ak}',
  'rocketmq.client.secretKey' = '${secret_sk}',
  'rocketmq.source.filter.tag' = '*',
  'rocketmq.source.startup.scan.mode' = 'latest',
  'rocketmq.source.pull.batch.size' = '32',
  'rocketmq.source.pull.interval.ms' = '100',
  'rocketmq.source.pull.suspend.timeout' = '30000',
  'rocketmq.client.message.field.delimiter' = ';',
  'rocketmq.client.message.line.delimiter' = '\n',
  'rocketmq.client.message.encoding' = 'UTF-8',
  'rocketmq.client.message.length.check' = 'NONE',
  'rocketmq.client.timeZone' = 'Asia/Shanghai',
  'rocketmq.client.partition.discovery.interval.ms' = '10000'
);

连接与鉴权参数(rocketmq.client.*,Source/Sink 通用):

参数是否必填默认值说明
rocketmq.client.endpoints是无接入点地址(含端口)。RocketMQ 5.x 形如 rmq-cn-xxx-vpc.cn-hangzhou.rmq.aliyuncs.com:8080;4.x 独享实例形如 http://MQ_INST_xxx.cn-hangzhou.mq-internal.aliyuncs.com:8080。
rocketmq.client.namespace否无实例命名空间 / 实例 ID(如 MQ_INST_xxx)。使用 4.x 独享实例、Topic/Group 需按实例隔离时必填;5.x 独立域名接入点通常无需填写。
rocketmq.client.accessKey否无阿里云 AccessKey ID,开启 ACL 鉴权的实例必填。建议用密钥管理引用。
rocketmq.client.secretKey否无阿里云 AccessKey Secret,开启 ACL 鉴权的实例必填。严禁明文,建议密钥管理引用。
rocketmq.client.message.field.delimiter否,字段分隔符:将消息体按位置拆分为各列(Source)/将各列拼接为消息体(Sink)。样例用 ;。
rocketmq.client.message.line.delimiter否\n行分隔符:一条消息含多行记录时用于切分。
rocketmq.client.message.encoding否UTF-8消息体字符编码。
rocketmq.client.message.length.check否NONE列数长度校验:NONE 不校验;开启后字段数与表结构不符会报错/丢弃。
rocketmq.client.timeZone否系统时区时间类型字段解析所用时区,如 Asia/Shanghai。
rocketmq.client.partition.discovery.interval.ms否无(关闭)队列(分区)动态发现间隔(毫秒),用于自动感知 Topic 扩缩容,如 10000。

消费端参数(rocketmq.source.*):

参数是否必填默认值说明
rocketmq.source.topic是无读取的 Topic 名称。
rocketmq.source.group是无消费组(Group ID),需在控制台预先创建。
rocketmq.source.filter.tag否*Tag 过滤表达式,* 表示不过滤;多个 Tag 用 \|\| 分隔。
rocketmq.source.startup.scan.mode否latest启动消费位点:earliest(最早)/latest(最新)/timestamp(指定时间)/group_offsets(消费组已提交位点)。
rocketmq.source.pull.batch.size否32每次拉取的最大消息条数。压测大流量时可调大(如 256)。
rocketmq.source.pull.interval.ms否0相邻两次拉取的间隔(毫秒),控制拉取频率与背压。
rocketmq.source.pull.suspend.timeout否30000长轮询在服务端的挂起超时(毫秒):无消息时请求最长挂起时长。

作为 Sink

rocketmq.sink.delivery.guarantee 取 EXACTLY_ONCE 时,需实例与连接器版本支持事务。

CREATE TABLE rocketmq_sink (
  `user_id` STRING,
  `user_name` STRING,
  `action` STRING,
  `process_time` TIMESTAMP(3),
  `field_a` STRING,
  `field_b` STRING,
  `keys` STRING METADATA,
  `tags` STRING METADATA
) WITH (
  'connector' = 'rocketmq',
  'rocketmq.sink.topic' = 'sink',
  'rocketmq.sink.group' = 'PID-flink',
  'rocketmq.client.endpoints' = 'rmq-cn-xxx-vpc.cn-hangzhou.rmq.aliyuncs.com:8080',
  'rocketmq.client.accessKey' = '${secret_ak}',
  'rocketmq.client.secretKey' = '${secret_sk}',
  'rocketmq.sink.delivery.guarantee' = 'AT_LEAST_ONCE',
  'rocketmq.client.message.field.delimiter' = ';',
  'rocketmq.sink.key.columns' = 'field_a,user_name',
  'rocketmq.sink.key.columns.included' = 'true',
  'rocketmq.sink.tag.column' = 'field_b',
  'rocketmq.sink.tag.column.included' = 'false'
);

生产端参数(rocketmq.sink.*):

参数是否必填默认值说明
rocketmq.sink.topic是无写入的目标 Topic。
rocketmq.sink.group是无生产组(Producer Group ID)。
rocketmq.sink.delivery.guarantee否AT_LEAST_ONCE投递语义:NONE/AT_LEAST_ONCE/EXACTLY_ONCE(需实例与连接器版本支持事务)。
rocketmq.sink.key.columns否无指定作为消息 Key 的字段,多个用逗号分隔,如 field_a,user_name。用于消息查询与幂等去重。
rocketmq.sink.key.columns.included否true作为 Key 的字段是否同时写入消息体。true 保留在 body,false 仅作 Key 不进 body。
rocketmq.sink.tag.column否无指定作为消息 Tag 的字段,供下游按 Tag 过滤。
rocketmq.sink.tag.column.included否true作为 Tag 的字段是否同时写入消息体。false 表示仅作 Tag 不进 body。
说明

keys 与 tags 也可声明为可写元数据列(METADATA,不带 VIRTUAL),由 SELECT 直接赋值,与 rocketmq.sink.key.columns、rocketmq.sink.tag.column 是两种等效路径。上方示例同时给出两种写法,实际配置时选择其中一种即可。

RocketMQ 可用元数据列:

元数据类型读/写说明
topicSTRING读消息所属 Topic。
msg_idSTRING读消息全局唯一 ID。
store_timestampBIGINT读服务端存储时间戳(毫秒)。
born_timestampBIGINT读消息产生时间戳(毫秒)。
queue_idINT读队列 ID。
queue_offsetBIGINT读队列内 offset。
keysSTRING读/写消息 Key。
tagsSTRING读/写消息 Tag。