Apache Pulsar Producer(生产者) 是向 Pulsar Topic 发送消息的客户端组件。它负责将应用程序产生的事件、数据或命令发布到消息系统中,是构建实时数据管道的第一环。
Pulsar 的 Producer 设计灵活、高性能,支持同步/异步发送、批量发送、消息路由、去重、Schema 验证等高级功能。
📘 Pulsar Producer 详解
一、Producer 基本概念
1. 什么是 Producer?
- Producer 是消息的发布者,连接到 Pulsar Broker,向指定 Topic 发送消息。
- 每个 Producer 必须绑定一个 Topic。
- Producer 可以动态创建(自动或手动),并在连接失败时自动重连。
2. 核心职责
| 职责 | 说明 |
|---|---|
| ✅ 连接 Broker | 建立与 Pulsar 集群的连接 |
| ✅ 发送消息 | 向 Topic 写入消息 |
| ✅ 路由控制 | 决定分区 Topic 中消息发往哪个分区 |
| ✅ 批量发送 | 提升吞吐,减少网络开销 |
| ✅ 消息确认 | 接收 Broker 的 ACK,确保发送成功 |
| ✅ Schema 支持 | 验证消息格式,保证数据一致性 |
二、Producer 创建与配置(Java 示例)
// 1. 创建 Pulsar 客户端
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar://localhost:6650")
.build();
// 2. 构建 Producer
Producer<String> producer = client.newProducer(Schema.STRING)
.topic("persistent://mycompany/finance/payments")
.producerName("payment-service-v1") // 自定义生产者名称
.sendTimeout(30, TimeUnit.SECONDS) // 发送超时
.blockIfQueueFull(true) // 队列满时阻塞(否则抛异常)
.maxPendingMessages(1000) // 最大未确认消息数
.batchingEnabled(true) // 启用批量发送
.batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS) // 批量延迟
.compressionType(CompressionType.LZ4) // 压缩
.messageRoutingMode(MessageRoutingMode.RoundRobinPartition) // 分区路由策略
.create();
💡 提示:
Schema.STRING表示消息是字符串类型,Pulsar 支持多种 Schema(见后文)。
三、消息发送方式
1. 同步发送(Sync Send)
- 阻塞调用,等待 Broker 返回确认后再继续。
- 适用于关键业务,需确保每条消息成功发送。
MessageId msgId = producer.newMessage()
.value("Order #12345 paid")
.send(); // 阻塞直到收到 ACK
System.out.println("Message persisted: " + msgId);
⚠️ 缺点:吞吐较低,延迟高。
2. 异步发送(Async Send)
- 非阻塞,立即返回
CompletableFuture<MessageId>。 - 高吞吐场景推荐使用。
CompletableFuture<MessageId> future = producer.newMessage()
.value("Order #12346 paid")
.sendAsync();
// 添加回调
future.thenAccept(msgId -> {
System.out.println("Async send success: " + msgId);
}).exceptionally(ex -> {
System.err.println("Send failed: " + ex.getMessage());
return null;
});
✅ 优势:高吞吐、低延迟。
3. 批量发送(Batching)
- 多条消息打包成一个批次发送,显著减少网络请求数。
- 受以下参数控制:
| 参数 | 说明 |
|---|---|
batchingEnabled(true) | 开启批量 |
batchingMaxMessages(1000) | 每批最多消息数 |
batchingMaxPublishDelay(10ms) | 最大等待时间,超时即发送 |
batchingMaxSize(128KB) | 批次最大字节数 |
⚠️ 注意:若启用批处理,单条消息失败会导致整个批次重试(可通过
batchingPartitionSwitchFrequencyByPublishDelay优化)。
四、分区 Topic 的消息路由策略
当向 Partitioned Topic 发送消息时,Producer 需决定路由到哪个分区。
通过 .messageRoutingMode() 设置:
| 路由模式 | 说明 |
|---|---|
RoundRobinPartition | 轮询分配(默认),负载均衡 |
SinglePartition | 固定到一个分区(适合无 Key 场景) |
CustomPartition | 自定义逻辑(需实现 MessageRouter) |
| 按 Key 路由 | 如果设置了 key,自动按 Key 哈希分配 |
// 示例:按 Key 路由(常用于 Key_Shared 订阅)
producer.newMessage()
.key("user-123") // 关键:设置 Key
.value("purchase event")
.send();
✅ 推荐:使用 Key 路由 + Key_Shared 订阅,实现“相同用户的消息顺序处理”。
五、Producer 高级特性
1. 消息去重(Producer Deduplication)
- 防止因网络重试导致的重复消息。
- Broker 会记录
(producer_id, sequence_id),重复消息被丢弃。 - 需在 Namespace 级开启:
pulsar-admin namespaces set-deduplication mycompany/finance --enable
✅ 保证 恰好一次(Exactly-Once) 语义的前提之一。
2. Schema 支持(数据类型安全)
- Producer 可指定 Schema,确保消息格式正确。
- 支持:
STRING,JSON,AVRO,PROTOBUF,INT8/16/32/64,FLOAT/DOUBLE等。
// 使用 Avro Schema
Schema<MyEvent> schema = Schema.AVRO(MyEvent.class);
Producer<MyEvent> producer = client.newProducer(schema)
.topic("events-topic")
.create();
producer.send(new MyEvent("user-login", "alice"));
✅ 优势:类型安全、自动序列化、兼容性检查。
3. 压缩(Compression)
- 减少网络传输和存储开销。
- 支持:
NONE,LZ4,ZLIB,ZSTD,SNAPPY
.compressionType(CompressionType.ZSTD)
✅ 建议:高吞吐场景启用
ZSTD或LZ4。
4. 消息属性(Properties)
- 添加自定义元数据(Key-Value),不影响 payload。
producer.newMessage()
.value("Hello")
.property("source", "web")
.property("version", "1.0")
.send();
可用于路由、过滤、审计等。
5. 延迟消息(Deliver After)
- 消息发送后延迟一段时间才被消费者可见。
producer.newMessage()
.value("Reminder: Meeting in 10 mins")
.deliverAfter(10, TimeUnit.MINUTES)
.send();
实现原理:Broker 将消息暂存到内部延迟队列,到期后投递。
6. 事件时间(Event Time)
- 设置消息发生的时间,用于流处理窗口计算。
producer.newMessage()
.value("click event")
.eventTime(System.currentTimeMillis())
.send();
与
publish time(Broker 接收时间)不同。
六、Producer 生命周期管理
1. 自动重连与故障转移
- Producer 在 Broker 宕机或网络中断后,会自动重连。
- 支持服务发现(通过 ZooKeeper 或配置)。
2. 关闭 Producer
producer.close(); // 正常关闭
// 或
producer.closeAsync().thenRun(() -> System.out.println("Closed"));
⚠️ 忘记关闭会导致连接泄露。
3. Producer 数量控制
- 每个 JVM 实例建议复用
PulsarClient和Producer。 - 避免频繁创建/销毁 Producer。
七、监控与调优建议
| 指标 | 监控建议 |
|---|---|
send-rate | 每秒发送消息数 |
batching-rate | 批量发送效率 |
avg-publish-latency | 发送延迟(P99 ≤ 10ms) |
connection-count | Producer 连接数 |
unacknowledged-messages | 未确认消息数(防内存溢出) |
可通过 Prometheus + Grafana 监控 Pulsar Broker 暴露的指标。
八、最佳实践总结
| 实践 | 建议 |
|---|---|
| ✅ 使用异步 + 批量发送 | 提升吞吐,降低延迟 |
| ✅ 为关键消息设置 Key | 支持 Key_Shared 订阅 |
| ✅ 启用 Schema | 保证数据一致性 |
| ✅ 开启压缩 | 节省带宽与存储 |
| ✅ 启用去重 | 防止重复发送 |
✅ 设置合理的 maxPendingMessages | 防止 OOM |
✅ 使用有意义的 producerName | 便于排查问题 |
| ✅ 避免频繁创建 Producer | 复用客户端资源 |
九、可视化 Producer 工作流程
+---------------------+
| Application Logic |
+----------+----------+
|
v
+----------+----------+
| Pulsar Producer |
| - 消息构建 |
| - Schema 序列化 |
| - 压缩 |
| - 批量缓存 |
+----------+----------+
|
v
[Batch Timer] or [Batch Full]
|
v
+----------+----------+
| Network → Broker |
| - 路由到分区 |
| - 写入 BookKeeper |
+----------+----------+
|
v
ACK ← Broker
|
v
CompletableFuture.complete()
✅ 总结
| 特性 | 说明 |
|---|---|
| ✅ 灵活发送模式 | 同步、异步、批量 |
| ✅ 高吞吐设计 | 批处理 + 压缩 |
| ✅ 分区路由 | 支持轮询、Key 哈希 |
| ✅ 数据安全 | Schema 验证 |
| ✅ 恰好一次 | 去重 + 事务(需开启) |
| ✅ 延迟消息 | 支持定时投递 |
| ✅ 易于集成 | 多语言 SDK(Java, Python, Go, Node.js 等) |
📌 一句话总结:
Producer 是数据入口的大门 —— 合理配置发送模式、启用批处理与 Schema,是构建高性能、可靠消息系统的起点。
959

被折叠的 条评论
为什么被折叠?



