4. 流编排核心组件:数据源(Source)、处理节点(Processor)、数据汇(Sink)的职责与生命周期
流编排应用的本质是将数据采集、处理与输出拆解为三个可独立部署、可组合的组件。理解 Source、Processor、Sink 的职责边界与生命周期管理,是构建可靠边缘计算管线的第一步。本章从职责定义、状态转换、生命周期回调三个维度展开,并给出典型边缘场景下的组件协作示例。
4.1 三大组件的职责定义
在流编排运行时,每个组件都是一个独立的执行单元,通过连接器(Connector)与上下游通信。下表从输入、输出、核心行为三个维度对比三者的职责差异:
| 组件类型 | 输入 | 输出 | 核心职责 |
|---|---|---|---|
| Source(数据源) | 外部系统(HTTP API、MQTT、文件、数据库) | 内部数据流(Record / Event) | 连接外部、拉取/监听数据、反序列化、生成带时间戳的原始记录 |
| Processor(处理节点) | 上游 Source 或其他 Processor | 下游 Processor 或 Sink | 过滤、转换、聚合、富化、规则判断;可产生零到多条输出 |
| Sink(数据汇) | 上游 Processor 或 Source | 外部系统(HTTP POST、数据库、文件、边缘存储) | 序列化、批量写入、事务提交、失败重试与死信处理 |
边缘场景提示: 在边缘节点上,Source 通常需要支持断网缓存(offline buffering),Processor 应保持无状态以方便热更新,Sink 必须实现幂等写入以避免网络抖动导致的数据重复。
4.2 组件生命周期状态机
每个组件在流编排引擎内部都经历统一的状态转换。状态机确保组件在启动、运行、停止、故障恢复等阶段行为可预测。下图展示了完整的生命周期状态流转:
4.3 生命周期回调方法
每个组件必须实现以下四个核心回调方法,编排引擎在状态转换时自动调用:
// Source 示例:HTTP API 轮询数据源
public class HttpPollingSource implements Source {
private HttpClient client;
private String endpoint;
@Override
public void init(SourceContext ctx) {
// 1. 解析配置(URL、间隔、认证)
this.endpoint = ctx.getConfig().getString("endpoint");
this.client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
// 2. 预校验:测试连接是否可达
if (!healthCheck()) {
throw new SourceInitException("Endpoint unreachable: " + endpoint);
}
}
@Override
public void start(SourceCollector<Record> collector) {
// 进入事件循环:定时拉取 HTTP API
while (isRunning()) {
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.GET()
.build();
client.sendAsync(req, BodyHandlers.ofString())
.thenAccept(response -> {
List<Record> records = parseResponse(response.body());
records.forEach(collector::collect);
});
Thread.sleep(pollIntervalMs);
}
}
@Override
public void pause() {
// 暂停拉取,保留连接池
setPaused(true);
}
@Override
public void close() {
// 释放连接、关闭线程池
client.close();
}
}
Processor 与 Sink 的差异:
- Processor.init():加载 UDF(用户自定义函数)、初始化状态存储(如去重缓存)。
- Processor.process():接收上游记录,返回零到多条输出记录;支持异步回调。
- Sink.init():创建数据库连接池或文件句柄,校验目标表/路径是否存在。
- Sink.write():批量写入,实现事务性提交;失败时根据重试策略决定是否进入死信队列。
4.4 组件协作流程:一次完整的流处理
下图展示了一个边缘 HTTP API 采集场景下,三个组件如何协作完成一次数据流转:
4.5 组件生命周期管理最佳实践
- 资源隔离: 每个 Source 独占一个连接池,避免一个组件故障拖垮整个引擎。
- 优雅关闭: 在
close()中等待正在处理的记录完成(drain),设置超时防止永久阻塞。 - 状态持久化: Processor 的中间状态(如窗口聚合结果)应在
pause()时快照到本地存储,resume()时恢复。 - 故障恢复: 组件从
FAILED状态只能通过close()进入CLOSED,然后重新init();不允许直接从FAILED跳回RUNNING。
常见陷阱:
- 在
init()中启动线程或定时器 → 应推迟到start()中执行,否则 pause/resume 无法正确控制。 - Sink 的
write()抛出异常后未标记组件为FAILED→ 导致数据丢失且引擎无法触发恢复策略。 - Source 的
close()未关闭网络连接 → 边缘节点内存泄漏,长期运行后 OOM。