概述
Pulsar是建立在publish-subscribe模式(通常缩写为pub-sub)上的。在这种模式中,生产者将消息发布到主题。使用者订阅这些主题,处理传入的消息,并在处理完成时发送确认。
创建订阅后,Pulsar将保留所有消息,即使用户已断开连接。只有当使用者确认已成功处理保留的消息时,才会丢弃这些消息。
消息
消息是Pulsar的基本单元, 下面表格叙述的是pulsar 的基本组件。
组件 | 描述 |
---|---|
内容(Value/data payload) | 消息携带着数据。虽然说数据可以有自己的schema,但是所有的数据都包含原始的字节数据(raw bytes) |
Key | 数据可以有选择性的添加自己的数据key,可以额外的功能 例如: topic 压缩 |
属性(Properties) | 提供一个用户自定义的map 保存k-v |
生产者(producer)名称 | 可以发送消息的时候主动制定,如果没有自定义则会使用默认的名字 |
序列(Sequence)ID | 每个Pulsar的消息在他自身的topic中属于有序队列。这个序列ID就是表示在这个队列中的顺序。 |
发布时间 | 顾名思义表示消息的发布时间,这个是producer发布数据的时候自动产生的 |
Event时间 | 可选,默认为0。比如说应用服务可以在处理完成消息的时候自行添加一个时间戳。 |
TypedMessageBuilder | 可以使用它构建信息,设置message属性 例如 key 和 value 等等。 |
生产者
生产者是一个附加到主题并将消息发布到Pulsar的Broker的过程。Pulsar星Broker处理消息。
发送模式
生产者可以通过同步或者异步模式来发送消息
模式 | 描述 |
---|---|
同步发送 | 发送每条消息后会等待broker返回ack, 如果没有返回则以失败论处. |
异步发送 | 会将数据推送到blocking queue中。client会在后台将信息发送到broker中。如果queue 满(queue大小可以配置)produer会阻塞或者立即失败(这个也是取决于配置)。 |
压缩
在数据传输过程中可以使用数据压缩。 Pulsar 当前支持如下的压缩方式:
- LZ4
- ZLIB
- ZSTD
- SNAPPY
批量处理
启用批处理后,生产者将在单个请求中累积并发送一批消息。 批处理大小由最大消息数和最大发布延迟定义。 因此,待办事项的大小表示批处理的总数而不是消息的总数。
在Pulsar中,批次被跟踪存储存储不是以单条信息为单位,而是以batch为单位。消费者会将batch的数据拆分成一条一条的数据。然而,调度信息无论是否配置了batch总是以一条一条进行发送的。
通常情况下,只有所有消息都被consumer 发送ack了,这个batch才会被ack。这就意味着,非预期的失败、超时或者否定ack 都会导致整个批次信息的重传。
为了避免将已确认的消息批量分发给使用者,自Pulsar 2.6.0起,Pulsar引入了批处理索引确认。 启用批处理索引确认后,使用者将筛选出已确认的批处理索引,并将批处理索引确认请求发送给Broker。 Broker维护批次索引确认状态,并跟踪每个批次索引的确认状态,以避免将已确认的消息发送给使用者。 确认批处理消息的所有索引后,该批处理消息将被删除。
默认情况下批处理索引确认功能是关闭的(batchIndexAcknowledgeEnable=false)。可以在broker上通过设置这个配置打开这个功能。启用批处理索引确认会导致更多的内存开销
分块(Chunking)
启用分块时,请阅读以下说明:
- 批处理和分块不能同时启用。 要启用分块,必须预先禁用批处理。
- 仅持久性主题支持’分块’功能。
- 独占和故障转移订阅模式仅支持分块。
启用分块后(chunkingEnabled = true),如果消息大小大于允许的最大发布有效负载大小,则生产者将原始消息拆分为分块消息,并将带有分块元数据的消息分别按顺序发布给Broker。 在Broker方,分块的消息以与普通消息相同的方式存储在托管分类帐中。 唯一的区别是,使用者需要缓冲已分块的消息,并在收集完所有已分块的消息后将它们组合为真实消息。 托管分类帐中的分块消息可以与普通消息交织。 如果生产者未能发布消息的所有块,则如果消费者未能在到期时间内接收到所有块,则消费者可以使不完整的块失效。 默认情况下,过期时间设置为一小时。
使用者使用分块的消息并对其进行缓冲,直到使用者收到消息的所有分块为止。 然后,消费者将分块的消息缝合在一起,然后将它们放入接收者队列。 客户端使用来自接收者队列的消息。 使用者使用完整个大消息并对其进行确认后,使用者将在内部发送与该大消息相关联的所有组块消息的确认。 您可以在使用者上设置maxPendingChuckedMessage参数。 当达到阈值时,使用者通过静默地确认未分类的消息或通过将标记为未确认而要求Broker稍后重新传递它们来丢弃未分类的消息。
Broker不需要任何更改即可支持非共享订阅的分块。 Broker
仅使用chuckedMessageRate记录有关该主题的分块消息速率。
一个生产者和一个订购的消费者一起处理分块的消息
如下图所示,当一个topic具有一个生产者时,该生产者将分块的大消息与普通(非分块)消息一起发布在成块的消息中。 生产者以三个块M1-C1,M1-C2和M1-C3发布消息M1。 Broker将所有三个已分块的消息存储在托管分类帐(the managed-ledger)中,并以相同顺序分派给已排序的(独占/故障转移)使用者。 使用者将所有已分块的消息缓冲在内存中,直到接收到所有已分块的消息,然后将它们组合为一条消息,然后将原始消息M1移交给客户端。
注意: 提交信息是所有chunk组合起来以后 被客户端消费到最后才会一起提交ack
多个生产者和一个有序消费者处理分块
当多个发布者将分块消息发布到单个topic中时,Broker会将来自不同发布者的所有分块消息存储在同一托管分类帐中。如下所示
- 生产者1以三个块M1-C1,M1-C2和M1-C3发布消息M1。
- 生产者2以三个块M2-C1,M2-C2和M2-C3发布消息M2。
特定消息的所有分块消息仍然是按顺序排列的,但在托管分类帐中可能不是连续的。这给使用者带来了一些内存压力,因为使用者为每个大消息保留了单独的缓冲区,以聚合大消息的所有块并将它们组合为一条消息。