在 Pulsar 2.5.2 版本发布后的 1 个月,2020 年 6 月 18 日,Apache Pulsar 正式发布了 2.6.0 版本!

Pulsar 2.6.0 版本新增了诸多功能,并修复了大量漏洞,覆盖存储端、Broker 端、客户端、Pulsar Functions、Pulsar IO、Pulsar SQL、Pulsar proxy 和安全等多方面,一如既往地丰富和完善了 Pulsar 作为一个云原生流数据平台的能力。

2.6.0 版本总共接受了来自社区约 450 个 commits,越来越多的代码贡献来自于中国开发者,中国力量越发迅猛。

以下是 2.6.0 版本重要新增功能的详细信息。

Pulsar 核心

[PIP-37] 支持传输大消息体的消息

通过将大消息体的消息拆分成多个 chunk,该 PIP 支持生产和消费大消息体的消息。目前,该功能仅对 non-shared subscription 有效,并对客户端有改动。如需使用该功能,你需要将 Pulsar 客户端升级至 2.6.0。使用该特性可以在生产端启用消息 trunking 机制。

client.newProducer()
	.topic("my-topic")
	.enableChunking(true)
	.create();
  • 更多关于 PIP-37 的信息,参阅这里

  • 更多关于该功能的代码实现细节, 参阅 PR-4440

[PIP-39] 新增 system topic,用于存储 namespace 更改事件

在 Pulsar 2.6.0 以前,Pulsar 只能设置 namespace 级策略,属于同一 namespace 的所有 topic 都遵循相同的 namespace 策略,但许多用户希望能设置 topic 级别策略。另外,不使用和 namespace 级策略的实现方式是因为更多的 Topic 策略会加重 ZooKeeper 负担,而 system topic 的设计初衷是希望将 topic 策略存储在 topic(而不是 ZooKeeper)中。该 PIP 是实现 topic 级策略的第一步,基于此,未来能实现更多相关功能。

  • 更多关于 PIP-39 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-4955。

[PIP-45] 支持可插拔元数据接口

该 PIP 支持 Pulsar 使用其他 metastore 服务(而不是 ZooKeeper),并支持 ManagedLedger 使用 MetadataStore 接口。通过 MetadataStore 接口,能较容易地增加其他元数据服务(例如 etcd)。

  • 更多关于 PIP-45 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-5358。

[PIP-54] 支持在 batch index 级确认消息

在 Pulsar 2.6.0 以前,broker 仅在 batch message 级追踪消息确认状态。如果部分批量消息中已被确认,消息重新发送给 consumer 时仍会收到“部分批量消息已确认”的信息。该 PIP 支持在 batch index 级确认消息。默认情况下,该功能未开启。如需开启,你可以在 broker.conf 文件中设置。

batchIndexAcknowledgeEnable=true
  • 更多关于 PIP-54 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-6052。

[PIP-58] 支持 consumer 设置自定义消息重发延时

对于许多在线业务系统而言,业务逻辑处理时常出现各种异常,因此需要重新消费消息,且用户希望可以自定义设置延迟时间。在 Pulsar 2.6.0 之前,当客户端发送 nack 至 broker,Pulsar 会立刻重发消息。从 Pulsar 2.6.0 开始,你可以为每条消息设置重发延时。

Consumer<byte[]> consumer = pulsarClient.newConsumer(Schema.BYTES)
                .enableRetry(true)
                .receiverQueueSize(100)
                .deadLetterPolicy(DeadLetterPolicy.builder()
                	.maxRedeliverCount(maxRedeliveryCount)
                   .retryLetterTopic("persistent://my-property/my-ns/my-subscription-custom-Retry")
                        .build())
                .subscribe();

consumer.reconsumeLater(message, 10 , TimeUnit.SECONDS);
  • 更多关于 PIP-58 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-6449。

[PIP-60] 支持 SNI 路由,以支持更多 proxy server

在 Pulsar 2.6.0 之前,Pulsar 不支持使用其他 proxy(例如,Apache Traffic Server、HAProxy、Nginx 和 Envoy)的 SNI 路由,这些 proxy 的扩展性和安全性更高,并且大多支持 SNI 路由。SNI 路由能在不中断 SSL 连接的情况下,将流量路由至目的地。

  • 更多关于 PIP- 60 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-6566。

[PIP-61] 支持多个 advertised address

该 PIP 允许 broker 暴露多个 advertised listeners,并支持内网和外网流量分离。你可以在 broker.conf 文件中指定多个 advertised listeners。

advertisedListeners=internal:pulsar://192.168.1.11:6660,external:pulsar://110.95.234.50:6650

你也可以为客户端指定 listener 名称。

PulsarClient.builder()
.serviceUrl(url)
.listenerName("internal")
.build();
  • 更多关于 PIP-61 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-6903。

[PIP-65] Pulsar IO sources 支持 BatchSource

该 PIP 新增了以下功能:新增 BatchSource 接口,用于开发基于 batch 的 connector;新增 BatchSourceTriggerer 接口,用于触发 BatchSource 收集数据;提供了 BatchSourceExecutor 的系统实现。

  • 更多关于 PIP-65 的信息,参阅这里。

  • 更多关于该功能的代码实现细节, 参阅 PR-7090。

[Load balancer][PR-6772] 添加 ThresholdShedder 策略

ThresholdShedder 策略比 LoadSheddingStrategy 策略更灵活。ThresholdShedder 策略计算 broker 的平均资源使用情况。每个 broker 资源使用情况会与该平均值进行对比。如果超过(平均值+阈值),则触发 namespace bundle 转移至其他低负载 broker 。你可以在 broker.conf 文件中启用该功能。

loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.impl.ThresholdShedder

你也可以自定义 ThresholdShedder 策略的参数。

# The broker resource usage threshold.
# When the broker resource usage is greater than the pulsar cluster average resource usage,
# the threshold shedder will be triggered to offload bundles from the broker.
# It only takes effect in ThresholdSheddler strategy.
loadBalancerBrokerThresholdShedderPercentage=10

# When calculating new resource usage, the history usage accounts for.
# It only takes effect in ThresholdSheddler strategy.
loadBalancerHistoryResourcePercentage=0.9

# The BandWithIn usage weight when calculating new resource usage.
# It only takes effect in ThresholdShedder strategy.
loadBalancerBandwithInResourceWeight=1.0

# The BandWithOut usage weight when calculating new resource usage.
# It only takes effect in ThresholdShedder strategy.
loadBalancerBandwithOutResourceWeight=1.0

# The CPU usage weight when calculating new resource usage.
# It only takes effect in ThresholdShedder strategy.
loadBalancerCPUResourceWeight=1.0

# The heap memory usage weight when calculating new resource usage.
# It only takes effect in ThresholdShedder strategy.
loadBalancerMemoryResourceWeight=1.0

# The direct memory usage weight when calculating new resource usage.
# It only takes effect in ThresholdShedder strategy.
loadBalancerDirectMemoryResourceWeight=1.0

# Bundle unload minimum throughput threshold (MB), avoiding bundle unload frequently.
# It only takes effect in ThresholdShedder strategy.
loadBalancerBundleUnloadMinThroughputThreshold=10
  • 更多关于该功能的代码实现细节, 参阅 PR-6772。

[Key Shared][PR-6791] 在 Key_Shared 订阅中增加一致性 hashing 分配

在 Pulsar 2.6.0 之前,Key_Shared 订阅是通过使用 hash range 自动分裂来实现,该方法基于在新 consumer 加入或离开时分裂现有已分配 hash range。

Pulsar 2.6.0 为 Key_Shared 订阅新增一致性 hash 分配。你可以在 broker.conf 文件中启用该功能。自动分裂(auto split)方法仍默认开启。

# On KeyShared subscriptions, with default AUTO_SPLIT mode, use splitting ranges or
# consistent hashing to reassign keys to new consumers
subscriptionKeySharedUseConsistentHashing=false

# On KeyShared subscriptions, number of points in the consistent-hashing ring.
# The higher the number, the more equal the assignment of keys to consumers
subscriptionKeySharedConsistentHashingReplicaPoints=100

后续 Pulsar 版本计划默认开启一致性 hash 分配功能。

  • 更多关于该功能的代码实现细节, 参阅 PR-6791。

[Key Shared][PR-7106][PR-7108] 解决了新增 consumer 时,KeyShared dispatcher 出现的乱序问题

该 PR 对 Key_Shared 订阅功能非常重要。在 Pulsar 2.6.0 之前,当新增 consumer(c2)进入且现有 consumer(c1)退出时,顺序在 Key_Shared dispatcher 中不能保证。这是因为之前分配至 c1 的消息和 key 可能路由至 c2,这可能导致 Key_Shared 订阅中同一个 key 的消息顺序分发保证失效。

该 PR 做出了以下改动:为了保证消息按序分配,在之前的消息被确认之前,新增 consumer 会变成“暂停”状态。

如果你仍想使用松散的顺序分发保证,可以在 consumer 端进行以下设置。

pulsarClient.newConsumer()
	.keySharedPolicy(KeySharedPolicy.autoSplitHashRange()。setAllowOutOfOrderDelivery(true))
	.subscribe();
  • 更多关于该功能的代码实现细节, 参阅 PR-7106 and PR-7108。

[Key Shared][PR-5928] 支持 key hash range reader

该 PR 支持 reader 读取某几个 hash range 的消息。Broker 仅发送 key 的 hash 在 hash range 范围内的消息。

另外,你也可以为 reader 指定多个 key hash range。

pulsarClient.newReader()
                    .topic(topic)
                    .startMessageId(MessageId.earliest)
                    .keyHashRange(Range.of(0, 10000), Range.of(20001, 30000))
                    .create();
  • 更多关于该功能的代码实现细节, 参阅 PR-5928。

[PR-5390] 将基于 JNI 的库替换成 AirCompressor(Java 压缩库)

在 Pulsar 2.6.0 之前,基于 JNI 的库用于压缩数据,但这些库有容量开销,且会影响 JNI 开销(通常它在压缩较小 payload 时计算)。

该 PR 将 LZ4、ZStd 和 Snappy 的压缩库替换成 AirCompressor,它是 Presto 使用的纯 Java 压缩库。

  • 更多关于该功能的代码实现细节, 参阅 PR-5390。

[PR-5985] 支持多个 Pulsar 集群使用相同的 BookKeeper 集群

该 PR 允许多个 Pulsar 集群使用指定 BookKeeper 集群(通过指定 BookKeeper 客户端至 BookKeeper 集群的 ZooKeeper 连接字符串)。

该 PR 新增配置项 bookkeeperMetadataServiceUri,用于发现 BookKeeper 集群元数据存储和使用元数据服务 URI,以初始化 BookKeeper 客户端。

# Metadata service uri that bookkeeper is used for loading corresponding metadata driver
# and resolving its metadata service location.
# This value can be fetched using `bookkeeper shell whatisinstanceid` command in BookKeeper cluster.
# For example: zk+hierarchical://localhost:2181/ledgers
# The metadata service uri list can also be semicolon separated values like below:
# zk+hierarchical://zk1:2181;zk2:2181;zk3:2181/ledgers
bookkeeperMetadataServiceUri=
  • 更多关于该功能的代码实现细节, 参阅 PR-5985。

[PR-6077] 支持在所有 subscription 已消费至最新消息后,删除非活跃 topic

在 Pulsar 2.6.0 之前,Pulsar 支持删除非活跃 topic(这些 topic 不包括 producer 和 subscription)。该 PR 支持当所有 topic 的 subscription 已消费至最新消息后且不存在活跃 producer 或 consumer 时,删除非活跃 topic。

你可以在 broker.conf 文件中设置使用该功能。计划将来能在 namespace 级使用该功能。

# Set the inactive topic delete mode. Default is delete_when_no_subscriptions
# 'delete_when_no_subscriptions' mode only delete the topic which has no subscriptions and no active producers
# 'delete_when_subscriptions_caught_up' mode only delete the topic that all subscriptions has no backlogs(caught up)
# and no active producers/consumers
brokerDeleteInactiveTopicsMode=delete_when_no_subscriptions
  • 更多关于该功能的代码实现细节, 参阅 PR-6077。

[PR-6634] 新增 flag,用于在内存溢出时忽略 broker 宕机

Topic 出现高 dispatch rate 时,可能导致 broker 短暂出现 OOM。一旦内存被释放,broker 可以在几分钟内恢复正常。但在 Pulsar 2.4.0(更多信息,参阅 PR-4196)中,内存溢出时重启 broker 会导致集群不稳定(topic 会在 broker 之间移动)、重启多个 broker 并扰乱其它 topic。该 PR 新增 flag,在内存溢出时忽略 broker 宕机,避免集群不稳定。

  • 更多关于该功能的代码实现细节, 参阅 PR-6634。

[PR-6668] 支持配置 ZooKeeper 缓存失效时间

在 Pulsar 2.6.0 之前,无法设置 ZooKeeper 缓存失效时间,但有许多场景需要设置该值。

现在,你可以在 broker.conf 文件中设置 ZooKeeper 缓存失效时间。

# ZooKeeper cache expiry time in seconds
zooKeeperCacheExpirySeconds=300
  • 更多关于该功能的代码实现细节, 参阅 PR-6668。

[PR-6719] 优化了 consumer 获取批量消息功能

当 consumer 向 broker 发送获取消息请求时,该请求包括获取消息数量(告知 broker 需要发送多少条消息至 consumer)。如果 producer 使用批量功能生产消息,broker 会根据 entry(而不是单条消息)将数据存储在 BookKeeper 或 broker 缓存。处理 consumer 获取请求时,消息数量和 entry 数量之间的映射存在问题。

该 PR 新增了 avgMessagesPerEntry 变量,用于记录存储在每条 entry 中的平均消息数量,并在 broker 发送消息至 consumer 时更新平均消息数量。处理 consumer 获取请求时,avgMessagesPerEntry 变量映射获取请求数量至 entry 数量。另外,该 PR 向 consumer stats 中增加了 avgMessagePerEntry 指标信息。

你可以在 broker.conf 中启用 preciseDispatcherFlowControl

# Precise dispatcher flow control according to history message number of each entry
preciseDispatcherFlowControl=false
  • 更多关于该功能的代码实现细节, 参阅 PR-6719。

[PR-7078] 为 topic 新增精确发布速率限制

在 Pulsar 2.6.0 之前,Pulsar 支持发布速率限制,但它并非精确控制。而现在,你可以在 broker.conf 文件中启用 topic 精确发布速率限制功能。

preciseTopicPublishRateLimiterEnable=true
  • 更多关于该功能的代码实现细节, 参阅 PR-7078。

[PR-7154] 支持 entry 检查延迟

在 Pulsar 2.6.0 之前,新增 entry 检查延迟是 10 ms(且用户无法设置该值)。现在,对于消费延迟敏感的场景,你可以在 broker.conf 文件中将新增 entry 检查延迟设置成更小值(可能降低消费吞吐)或 0。

managedLedgerNewEntriesCheckDelayInMillis=10
  • 更多关于该功能的代码实现细节, 参阅 PR-7154。

[Schema] [PR-7139] KeyValue schema 支持 null key 和 null value。

  • 更多关于该功能的代码实现细节, 参阅 PR-7139。

[PR-7116] 支持设置 maxLedgerRolloverTimeMinutes 参数,用于触发 ledger 切换

该 PR 实现了一个监测线程,用于检查当前 topic ledger 是否满足 managedLedgerMaxLedgerRolloverTimeMinutes 条件并触发 ledger 切换使配置生效。如果触发 ledger 切换,你可以关闭当前 ledger 并释放当前 ledger 的存储空间。对于不常使用的 topic,当前 ledger 数据可能失效,且当前切换操作仅适用于新增 entry 时。很显然,这会浪费磁盘空间。

监测线程在固定间隔时间检查 ledger 是否需要切换。你可以通过 managedLedgerMaxLedgerRolloverTimeMinutes 设置该时间间隔。

  • 更多关于该功能的代码实现细节, 参阅 PR-7116。
Proxy

[PR-6473] 新增用于获取 connection 和 topic stats 的 REST API

在 Pulsar 2.6.0 之前,Pulsar proxy 没有获取 proxy 内部信息的 stats,例如,有效连接、topic stats(log 级)和其它信息。

该 PR 新增用于获取 connection 和 topic stats 的 REST API。

  • 更多关于该功能的代码实现细节, 参阅 PR-6473。
Admin

[PR-6331] 新增 get-message-by-id 命令

该 PR 新增 get-message-by-id 命令,支持通过 ledger ID 和 entry ID 检查单条信息。

  • 更多关于该功能的代码实现细节, 参阅 PR-6331。

[PR-6383] 新增强制删除 subscription 功能

该 PR 新增 deleteForcefully 方法,用于强制删除 subscription。

  • 更多关于该功能的代码实现细节, 参阅 PR-6383。
Functions

[PR-6895] 内置函数

支持像创建内置 connector 一样创建内置 function。

  • 更多关于该功能的代码实现细节, 参阅 PR-6895。

[PR-6031] 新增 Go function 心跳和 gRPC 服务

  • 更多关于该功能的代码实现细节, 参阅 PR-6031。

[PR-6348] 支持自定义系统配置

该 PR 支持在提交 function 时自定义系统变量。该功能可以通过系统变量传递认证信息。

  • 更多关于该功能的代码实现细节, 参阅 PR-6348。

[PR-6602] 分离 function worker 和 broker 的 TLS 配置

  • 更多关于该功能的代码实现细节, 参阅 PR-6602。

[PR-6954] 支持在 function 和 source 中创建 consumer

在 Pulsar 2.6.0 之前,你能通过 function context 和 source context 创建 publisher,但不能创建 consumer。该 PR 修复了这一问题。

  • 更多关于该功能的代码实现细节, 参阅 PR-6954。
Pulsar SQL

[PR-6325] 支持 KeyValue schema

在 Pulsar 2.6.0 之前,Pulsar SQL 无法读取 KeyValue schema 数据。

该 PR 支持 KeyValue schema,并为 key field 名称新增前缀 key.,为 value field 名称新增前缀 value.

  • 更多关于该功能的代码实现细节, 参阅 PR-6325。

[PR-4847] 支持多个 Avro schema 版本

在 Pulsar 2.6.0 之前,如果 topic 有多个 Avro schema,使用 Pulsar SQL 查询 topic 的数据会引起一些问题。从 Pulsar 2.6.0 开始,如需查询 topic 中的数据,可以更新 schema,该 schema 可以兼容 topic 中的所有 schema。

  • 更多关于该功能的代码实现细节, 参阅 PR-4847。
Java client

[PR-6648] 新增 API,用于在关闭 producer 时,Pulsar 客户端会继续等待正在传输的消息传输完成

在 Pulsar 2.6.0 之前,当关闭 producer 时,Pulsar 客户端会立刻让正在传输的消息失效(即使消息已在 broker 持久化)。大部分情况下,用户希望能在关闭 producer 前等待正在传输的消息完成(而不是使这些消息失效),但 Pulsar 客户端 lib 未实现该功能。

该 PR 支持通过 flag(控制是否等待正在传输的消息)关闭 API。你可以在关闭 producer 之前等待正在传输的消息,Pulsar 客户端不会立即使这些消息失效。

  • 更多关于该功能的代码实现细节, 参阅 PR-6648。

[PR-6760] 支持从输入流中动态加载 TLS certs/key

在 Pulsar 2.6.0 之前,Pulsar 客户端提供 TLS 认证功能,默认 TLS provider AuthenticationTls 的值为 cert 和 key 文件的文件路径,但在有些应用场景中很难为 TLS 认证存储 cert 或 key。

该 PR 为 AuthenticationTls 新增流支持,以提供 X509Certs 和 PrivateKey(当指定 provider 出现流变化时,PrivateKey 会自动更新)。

  • 更多关于该功能的代码实现细节, 参阅 PR-6760。

[PR-6825] 异步发送消息时,如果程序抛出异常,系统会返回 sequence ID

在 Pulsar 2.6.0 之前,如果异步发送消息失败,程序会抛出异常,但并不显示哪些消息不正常,用户也无法了解需要重试哪些消息。

此次改动更新了客户端。当抛出异常时,程序会设置 sequenceId org.apache.pulsar.client.api.PulsarClientException

  • 更多关于该功能的代码实现细节, 参阅 PR-6825。
参考信息

Pulsar

  • 如需下载 Apache Pulsar 2.6.0,点击这里。

  • 更多关于 Apache Pulsar 2.6.0 的信息,查阅 2.6.0 版本说明 和 2.6.0 PR 列表。

任何问题或建议,欢迎通过 Pulsar mailing list 或 Slack 联系我们:

  • Pulsar mailing list: users@pulsar.apache.org and dev@pulsar.apache.org。

  • Pulsar Slack: https://apache-pulsar.slack.com/.

期待你为 Pulsar 的发展添砖加瓦。

如果你对 Pulsar 示例、demo、工具或扩展感兴趣,欢迎查阅 StreamNative GitHub。