Pulsar 与流处理引擎集成:Apache Flink 详解

Pulsar 与 Apache Flink 的集成 是构建现代实时数据架构的核心组合。Pulsar 作为高性能、持久化、多租户的 消息与事件流平台,而 Flink 作为强大的 流批一体计算引擎,二者结合可实现:

  • ✅ 精确一次(Exactly-Once)语义
  • ✅ 低延迟流处理
  • ✅ 事件时间窗口计算
  • ✅ 状态管理与容错
  • ✅ 流批统一处理

这一切通过官方维护的 pulsar-flink-connector 实现,支持 Flink 1.14+ 版本。


📘 Pulsar 与流处理引擎集成:Apache Flink 详解


一、为什么选择 Pulsar + Flink?

需求Pulsar 提供Flink 提供
✅ 高吞吐消息传递分层架构、BookKeeper 持久化-
✅ 多租户与资源隔离Tenant/Namespace 隔离-
✅ 消息回放与重处理保留策略、游标重置-
✅ 精确一次处理Producer 去重 + 事务(可选)Checkpoint + 两阶段提交
✅ 窗口计算-滚动、滑动、会话窗口
✅ 状态管理-RocksDB / Memory State Backend
✅ 事件时间处理事件时间戳(Event Time)Watermark 机制
✅ 容错恢复BookKeeper 高可用Checkpoint / Savepoint

Pulsar 是“管道”,Flink 是“处理器” —— 两者协同,构建完整的实时数据流水线。


二、pulsar-flink-connector 核心特性

官方连接器:pulsar-flink-connector
GitHub:apache/pulsar-flink

1. 支持的 Flink 版本
Flink 版本Connector Artifact
Flink 1.14+pulsar-flink-connector_2.12_2.11
Flink 1.17+推荐使用 pulsar-flink-connector(统一模块)
2. 核心功能
功能说明
Source(输入)从 Pulsar Topic 读取消息
Sink(输出)将处理结果写入 Pulsar Topic
Exactly-Once 语义基于 Flink Checkpoint + Pulsar Ack
支持 Event Time自动提取事件时间戳
支持 SchemaJSON、Avro、Protobuf 自动反序列化
支持 Key_Shared 订阅保证 Key 级顺序
支持事务写入(Flink 1.15+)实现端到端 Exactly-Once

三、集成配置与依赖

1. Maven 依赖(Flink 1.17 + Pulsar 3.0+)
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-java</artifactId>
    <version>1.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-streaming-java</artifactId>
    <version>1.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.pulsar</groupId>
    <artifactId>pulsar-flink-connector</artifactId>
    <version>3.0.0</version>
</dependency>

⚠️ 注意版本兼容性!建议使用 Pulsar 2.10+ 和 Flink 1.14+。

2. 打包方式
  • 使用 maven-shade-plugin 打成 Fat JAR。
  • 或将 pulsar-flink-connector.jar 放入 Flink 的 lib/ 目录。

四、Flink 作为 Pulsar Source(消费消息)

1. 基本配置
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

// 启用 Checkpoint(Exactly-Once 的基础)
env.enableCheckpointing(10_000, CheckpointingMode.EXACTLY_ONCE);

// 创建 Pulsar Source
PulsarSource<String> source = PulsarSource.builder()
    .serviceUrl("pulsar://localhost:6650")
    .adminUrl("http://localhost:8080")
    .subscriptionName("flink-sub")
    .topic("persistent://public/default/input-topic")
    .deserializationSchema(PulsarDeserializationSchema.flinkSchema(Schema.STRING))
    .subscriptionType(SubscriptionType.Shared)
    .build();

// 添加 Source
DataStream<String> stream = env.fromSource(source, WatermarkStrategy.noWatermarks(), "Pulsar Source");
2. 支持 Event Time
// 提取事件时间
WatermarkStrategy<String> strategy = WatermarkStrategy.<String>forBoundedOutOfOrderness(Duration.ofSeconds(5))
    .withTimestampAssigner((event, timestamp) -> {
        // 假设消息中包含事件时间
        return extractEventTime(event);
    });

DataStream<String> stream = env.fromSource(source, strategy, "Pulsar Source");
3. 支持 Schema(Avro 示例)
Schema<User> pulsarSchema = Schema.AVRO(User.class);
PulsarDeserializationSchema<User> deserializer = 
    PulsarDeserializationSchema.pulsarSchema(pulsarSchema);

PulsarSource<User> source = PulsarSource.builder()
    .topic("users")
    .deserializationSchema(deserializer)
    .build();

五、Flink 作为 Pulsar Sink(写入消息)

1. 基本配置
// 处理后的流
DataStream<String> processedStream = stream.map(String::toUpperCase);

// 创建 Pulsar Sink
PulsarSink<String> sink = PulsarSink.builder()
    .serviceUrl("pulsar://localhost:6650")
    .adminUrl("http://localhost:8080")
    .topic("persistent://public/default/output-topic")
    .serializationSchema(PulsarSerializationSchema.flinkSchema(Schema.STRING))
    .producerConfigurations(
        ProducerConfigurationData.builder()
            .batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS)
            .compressionType(CompressionType.LZ4)
            .build()
    )
    .build();

// 添加 Sink
processedStream.sinkTo(sink);
2. 支持 Exactly-Once 写入(事务模式)
PulsarSink<String> sink = PulsarSink.builder()
    .serviceUrl("pulsar://localhost:6650")
    .adminUrl("http://localhost:8080")
    .topic("output-topic")
    .serializationSchema(PulsarSerializationSchema.flinkSchema(Schema.STRING))
    .enableTransaction(true)  // 启用事务
    .build();

✅ 要求 Flink Checkpoint + Pulsar 事务支持。


六、完整示例:实时词频统计

public class WordCountFromPulsar {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.enableCheckpointing(10_000, CheckpointingMode.EXACTLY_ONCE);

        // Source: 从 Pulsar 读取
        PulsarSource<String> source = PulsarSource.builder()
            .serviceUrl("pulsar://localhost:6650")
            .adminUrl("http://localhost:8080")
            .topic("persistent://public/default/sentences")
            .subscriptionName("flink-wordcount")
            .deserializationSchema(PulsarDeserializationSchema.flinkSchema(Schema.STRING))
            .build();

        DataStream<String> lines = env.fromSource(source, WatermarkStrategy.noWatermarks(), "Pulsar Source");

        // 处理:分词 + 计数
        DataStream<Tuple2<String, Integer>> counts = lines
            .flatMap((String line, Collector<String> out) -> {
                for (String word : line.toLowerCase().split("\\W+")) {
                    if (word.length() > 0) out.collect(word);
                }
            })
            .keyBy(value -> value)
            .window(TumblingProcessingTimeWindows.of(Time.seconds(10)))
            .sum(1);

        // Sink: 写回 Pulsar
        PulsarSink<Tuple2<String, Integer>> sink = PulsarSink.builder()
            .serviceUrl("pulsar://localhost:6650")
            .adminUrl("http://localhost:8080")
            .topic("persistent://public/default/word-count")
            .serializationSchema(PulsarSerializationSchema.flinkSchema(Schema.AVRO(WordCount.class)))
            .build();

        counts.sinkTo(sink);

        env.execute("Pulsar WordCount");
    }
}

七、部署方式

方式说明
Flink Job Cluster提交 JAR 到独立 Flink 集群
Flink on Kubernetes使用 flink-kubernetes-operator 部署
YARN / Mesos企业已有资源管理平台
Standalone测试环境

✅ 推荐生产环境使用 Flink on Kubernetes,弹性伸缩、高可用。


八、性能调优建议

优化点建议
启用 Checkpoint间隔 5~10 秒,模式 EXACTLY_ONCE
合理设置并行度匹配 Pulsar Topic 分区数
批量写入Sink 启用 batching
压缩启用 LZ4ZSTD
状态后端生产用 RocksDB,测试用 Memory
监控集成 Prometheus + Grafana

九、监控与可观测性

指标采集方式
Flink Checkpoint 时长Flink Metrics → Prometheus
Pulsar 消费延迟pulsar_broker_subscription_backlog
Flink 处理延迟Flink Web UI 或 Metrics
端到端延迟在消息中注入时间戳

✅ 总结

特性说明
无缝集成pulsar-flink-connector 官方维护
Exactly-OnceCheckpoint + 事务保证
事件时间处理支持窗口计算
Schema 支持类型安全
云原生部署Flink on K8s + Pulsar on K8s
流批统一Flink 批处理模式读取历史消息

📌 一句话总结

Pulsar + Flink = 实时数据系统的“黄金搭档” —— Pulsar 提供可靠的消息管道,Flink 提供强大的计算能力,二者通过 pulsar-flink-connector 紧密集成,构建端到端的实时流处理平台。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值