【消息中间件】新一代消息中间件Apache Pulsar将成主流?为什么被各大巨头热衷?

诞生的场景背景

Kafka 作为一款明星级产品,能够彻底满足海量数据场景下高吞吐、高并发需求,在短短几年内,已经被阿里、腾讯、百度、字节跳动、Netflix、Twitter 等超一线大厂视为技术核心。然而,技术的世界从没有“三十年河东三十年河西”的说法,夸张地比喻一下:很多技术经常是今天诞生、明天爆火、后天淘汰

Kafka 被誉为消息传递系统之王,它全面具备:高吞吐量、低延迟、容错、持久性、可伸缩性,尤其是广为人知的高吞吐量,Kafka 每秒大约可以生产约 25 万消息(50 MB),每秒处理 55 万消息(110 MB)!Kafka 还有一个巨大的优势就是容错,它具备一个固有功能,可以自行应对集群中的节点故障。

 

 

Kafka 当然很强,但在运维和实践过程中,却也始终存在着一些棘手的问题。例如:

 

扩展性较差,剥离 Broker 意味着必须复制 topic 分区和副本,效率很低;

缺乏一致性,一旦 API 发生变化很有可能出现问题;

存储成本非常高,几乎没有人用Kafka长时间存储数据;

没有与租户完全隔离的本地多租户,需要自行配置解决方案。

 

俯瞰技术生态,有没有一个平台,能够既拥有 Kafka 的优势,又规避它的缺陷,同时还融合了各个 MQ 的一系列特性呢?是的,你想要的完美,下一代云原生消息平台、Apache 顶级项目 Pulsar 都可以满足!

Pulsar是什么?‍

Pulsar 是一个用于服务器到服务器的消息系统,具有多租户、高性能等优势。 Pulsar 最初由 Yahoo 开发,目前由 Apache 软件基金会管理。

Pulsar 采用 发布-订阅的设计模式(简称 pub-sub), 该设计模式中,producer发布消息到topic,Consumer订阅topic、处理发布的消息,并在处理完成后发送确认。

一旦创建订阅,即使 consumer 断开连接,Pulsar 仍然可以保存所有消息。 在 consumer 确认消息已处理成功后,才会删除消息。

 

Pulsar 不仅可以如同 Kafka 一样处理高速率实时场景,还能支持传统的标准消息队列模式,例如多消费者和失效备援订阅等。

 

一个 Pulsar 系统,直接让你拥有 RabbitMQ + RocketMQ + Kafka 的各项特性!更惊艳的是,Pulsar 采用云原生架构,它的架构设计能够充分利用分布式且能弹性扩容云端资源,永久性告别性能不足。

Pulsar 消息发送模式架构图

 

目前,Pulsar 已经被腾讯、智联招聘、涂鸦智能、中国移动、中国电信、360、达达集团(京东到家)、苏宁、平安证券、华为等各个领域的巨头争先广泛实践,有全面赶超 Kafka 的趋势,和当年阿里推动 Flink 取代 Spark 的态势非常相似!

Pulsar 的关键特性如下:

  • Pulsar 的单个实例原生支持多个集群,可跨机房在集群间无缝地完成消息复制。

  • 极低的发布延迟和端到端延迟。

  • 可无缝扩展到超过一百万个 topic。

  • 简单的客户端 API,支持 Java、Go、Python 和 C++。

  • 支持多种 topic 订阅模式(独占订阅、共享订阅、故障转移订阅)。

  • 通过 Apache BookKeeper 提供的持久化消息存储机制保证消息传递 。

  • 由轻量级的 serverless 计算框架 Pulsar Functions 实现流原生的数据处理。

  • 基于 Pulsar Functions 的 serverless connector 框架 Pulsar IO 使得数据更易移入、移出 Apache Pulsar。

  • 分层式存储可在数据陈旧时,将数据从热存储卸载到冷/长期存储(如S3、GCS)中。

架构概述

在最高级别,一个Pulsar实例由一个或多个Pulsar集群组成。实例中的群集可以在它们之间复制数据。单个 Pulsar 集群由以下三部分组成:

  • 一个或者多个 broker 负责处理和负载均衡 producer 发出的消息,并将这些消息分派给 consumer;Broker 与 Pulsar 配置存储交互来处理相应的任务,并将消息存储在 BookKeeper 实例中(又称 bookies);Broker 依赖 ZooKeeper 集群处理特定的任务,等等。

  • 包含一个或多个 bookie 的 BookKeeper 集群负责消息的持久化存储

  • 一个Zookeeper集群,用来处理多个Pulsar集群之间的协调任务。

下图为一个 Pulsar 集群:

Brokers

Pulsar的broker是一个无状态组件, 主要负责运行另外的两个组件:

  • 一个 HTTP 服务器, 它暴露了 REST 系统管理接口以及在生产者和消费者之间进行 Topic查找的API。

  • 一个调度分发器, 它是异步的TCP服务器,通过自定义 二进制协议应用于所有相关的数据传输。

Messages are typically dispatched out of a managed ledger cache for the sake of performance,  the backlog exceeds the cache size. 如果积压的消息对于缓存来说太大了, 则Broker将开始从BookKeeper那里读取Entries(Entry同样是BookKeeper中的概念,相当于一条记录)。

最后,为了支持全局Topic异地复制,Broker会控制Replicators追踪本地发布的条目,并把这些条目用Java 客户端重新发布到其他区域。

集群

一个Pulsar实例由一个或多个Pulsar集群组成。集群又包括:

  • 一个或者多个Pulsar brokers

  • 一个ZooKeeper协调器,用于集群级别的配置和协调

  • 一组BookKeeper的Bookies用于消息的 持久化存储

集群间可以通过异地复制进行消息同步

元数据存储

Pulsar使用Apache Zookeeper进行元数据存储,集群配置和协调。在Pulsar实例中:

  • 配置与仲裁存储: 存储租户,命名域和其他需要全局一致的配置项

  • 每个集群有自己独立的ZooKeeper保存集群内部配置和协调信息,例如归属信息,broker负载报告,BookKeeper ledger信息(这个是BookKeeper本身所依赖的)等等。

持久化存储

Pulsar为应用程序提供有保证的消息传递。如果消息成功到达Pulsar代理,它将被传递到其预定目标。

为了提供这种保证,未确认送达的消息需要持久化存储直到它们被确认送达。 This mode of messaging is commonly called . 在Pulsar内部,所有消息都被保存并同步N份,例如,2个服务器保存四份,每个服务器上面都有镜像的RAID存储。

Apache BookKeeper

Pulsar用 Apache BookKeeper作为持久化存储。 BookKeeper是一个分布式的预写日志(WAL)系统,有如下几个特性特别适合Pulsar的应用场景:

  • 它使Pulsar可以利用许多独立的日志,称为分类账。随着时间的推移,可以为主题创建多个分类帐。

  • 为按条目复制的顺序数据提供了非常高效的存储。

  • 保证了多系统挂掉时ledgers的读取一致性。

  • 提供不同的Bookies之间均匀的IO分布的特性。

  • 它在容量和吞吐量上都可以水平扩展。通过将更多的bookies添加到群集中,可以立即增加容量。

  • Bookies被设计成可以承载数千的并发读写的ledgers。 使用多个磁盘设备,一个用于日志,另一个用于一般存储,这样Bookies可以将读操作的影响和对于写操作的延迟分隔开。

In addition to message data,  are also persistently stored in BookKeeper. Cursors是消费端订阅消费的位置。 BookKeeper让Pulsar可以用一种可扩展的方式存储消费位置。

At the moment, Pulsar supports persistent message storage. This accounts for the persistent in all topic names. 下面是一个示例:

persistent://tenant/namespace/topic

Pulsar也支持临时消息( (non-persistent) )存储。

下图展示了brokers和bookies是如何交互的

Ledgers

Ledger是一个只追加的数据结构,并且只有一个写入器,这个写入器负责多个BookKeeper存储节点(就是Bookies)的写入。 Ledger的条目会被复制到多个bookies。 Ledgers本身有着非常简单的语义:

  • Pulsar Broker可以创建ledeger,添加内容到ledger和关闭ledger。

  • 当一个ledger被关闭后,除非明确的要写数据或者是因为写入器挂掉导致ledger关闭,这个ledger只会以只读模式打开。

  • 最后,当ledger中的条目不再有用的时候,整个legder可以被删除(ledger分布是跨Bookies的)。

Ledger读一致性

BookKeeper的主要优势在于他能在有系统故障时保证读的一致性。 由于Ledger只能被一个进程写入(之前提的写入器进程),这样这个进程在写入时不会有冲突,从而写入会非常高效。 在一次故障之后,ledger会启动一个恢复进程来确定ledger的最终状态并确认最后提交到日志的是哪一个条目。 在这之后,能保证所有的ledger读进程读取到相同的内容。

Managed ledgers

考虑到Bookkeeper ledgers提供了一个单一的日志抽象,因此在ledger之上开发了一个库,它表示单个主题的存储层。managed ledgers即消息流的抽象,有一个写入器进程不断在流结尾添加消息,并且有多个cursors 消费这个流,每个cursor有自己的消费位置。

在内部,单个ledger使用多个BookKeeper分类账来存储数据。拥有多个ledger有两个原因:

  1. 在故障之后,原有的某个ledger不能再写了,需要创建一个新的。

  2. 当所有游标都使用了ledger包含的消息时,可以删除ledger。这允许定期滚动ledgers.

日志存储

在 BookKeeper中包含了, BookKeeper transaction logs 事务日志文件. 在更新到 ledger之前,bookie需要确保描述这个更新的事务被写到持久(非易失)存储上面。 在bookie启动和旧的日志文件大小达到上限(由 journalMaxSizeMB 参数配置)的时候,新的日志文件会被创建。

Pulsar proxy

Pulsar客户端和Pulsar集群交互的一种方式就是直连Pulsar brokers 。 然而,在某些情况下,这种直连既不可行也不可取,因为客户端并不知道broker的地址。 例如在云环境或者 Kubernetes 以及其他类似的系统上面运行Pulsar,直连brokers就基本上不可能了。

Pulsar proxy为集群中所有代理的单一网关,提供了解决此问题的方法。如果你选择运行Pulsar Proxy(这是可选的),所有的客户端连接将会通过这个代理而不是直接与brokers通信。

为了性能和容错,你可以运行任意个Pulsar proxy。

架构上来看,Pulsar Proxy从ZooKeeper上面读取他所需要的所有信息。 当启动代理时,你只需要提供用于集群独有和实例范围的配置存储的ZooKeeper连接串。 

下面是一个示例:

$ bin/pulsar proxy \
  --zookeeper-servers zk-0,zk-1,zk-2 \
  --configuration-store-servers zk-0,zk-1,zk-2

 

关于Pulsar proxy有一些比较重要的注意点:

  • 连接客户端不需要提供特定的配置就可以使用Pulsar代理。 除了更新用于服务URL的IP之外,你不需要为现有的应用更新客户端配置(例如你在Pulsar proxy上层架设运行了负载均衡器)。

  • Pulsar proxy支持TLS 加密 和 认证。

服务发现

客户端 需要能够使用单个 URL 与整个 Pulsar 实例进行通信。 Pulsar内部提供了服务发现的机制,你可以通过 配置Pulsar实例指南设置。

你也可以用你自己的服务发现系统。 如果您使用自己的系统,那么只有一个要求:当客户端对端点执行HTTP请求时,例如http://pulsar.us-west.example.com:8080,客户端需要重定向到所需集群中的活动代理,无论是通过DNS、HTTP或IP重定向还是其他方式。

下面这张图展示了Pulsar服务发现机制:

图中,Pulsar集群可以通过一个DNS名称寻址:pulsar-cluster.acme.com。 例如Python客户端,可以像这样访问这个Pulsar集群:

from pulsar import Client
client = Client('pulsar://pulsar-cluster.acme.com:6650')

Note In Pulsar, each topic is handled by only one broker. 客户端发出的读取,更新或删除主题的初始请求将发送给可能不是处理该主题的 broker 。 如果这个 broker 不能处理该主题的请求,broker 将会把该请求重定向到可以处理主题请求的 broker。

使用Docker容器搭建 Pulsar

可以在本地机器的 Docker 容器中运行单机模式的 Pulsar,进行本地开发和测试。MacOS、Linux、Windows 用户运行以下命令启动Pulsar:

$ docker run -it \

  -p 6650:6650 \

  -p 8080:8080 \

  --mount source=pulsardata,target=/pulsar/data \

  --mount source=pulsarconf,target=/pulsar/conf \

  apachepulsar/pulsar:2.7.2 \

  bin/pulsar standalone

关于此命令,需要注意以下几点:

  • 数据、元数据和配置被持久保存在Docker卷上,以便在每次重新启动容器时都不会“刷新”启动。有关卷的详细信息,请使用docker volume inspect<sourcename>

  • 对于Windows上的Docker,请确保将其配置为使用Linux容器

成功启动 Pulsar 后,你将看到如下所示的 INFO 级日志消息:

 

- INFO  - [main:WebService@213] - Web Service started at http://127.0.0.1:8080

- INFO  - [main:PulsarService@335] - messaging service is ready, bootstrap service on port=8080, broker url=pulsar://127.0.0.1:6650, cluster=standalone, configs=org.apache.pulsar.broker.ServiceConfiguration@4db60246

启动本地独立集群,将自动创建 public/default 命名空间。 自动创建的命名空间将用于开发用途。 所有Pulsar的topic主题都在命名空间中进行管理。

运行 Pulsar 客户端测试

Pulsar 支持多个客户端: Java、Go、<a href =“ client-libraries-python.md“>Python 和 C ++。 如果运行的是本地独立集群,则可以使用以下 URL 中的一个与其交互:

  • pulsar://localhost:6650

  • http://localhost:8080

以下示例展示了如何通过 Python 客户端的 API 快速入门 Pulsar。

直接从 PyPI 安装 Pulsar 的 Python 客户端库:

$ pip install pulsar-client

创建 consumer 并订阅 topic:

import pulsar

client = pulsar.Client('pulsar://localhost:6650')
consumer = client.subscribe('my-topic',
subscription_name='my-sub')

while True:
    msg = consumer.receive()
    print("Received message: '%s'" % msg.data())
    consumer.acknowledge(msg)

client.close()

启动 producer,发送测试消息:

import pulsar

client = pulsar.Client('pulsar://localhost:6650')
producer = client.create_producer('my-topic')

for i in range(10):
    producer.send(('hello-pulsar-%d' % i).encode('utf-8'))

client.close()

获取topic 数据

在Pulsar中,您可以使用REST、Java或命令行工具来控制系统的各个方面。在最简单的示例中,您可以使用curl来获取特定主题的统计信息,使用 Admin API:

$ curl http://localhost:8080/admin/v2/persistent/public/default/my-topic/stats | python -m json.tool

输出应如下所示:

{
  "averageMsgSize": 0.0,
  "msgRateIn": 0.0,
  "msgRateOut": 0.0,
  "msgThroughputIn": 0.0,
  "msgThroughputOut": 0.0,
  "publishers": [
    {
      "address": "/172.17.0.1:35048",
      "averageMsgSize": 0.0,
      "clientVersion": "1.19.0-incubating",
      "connectedSince": "2017-08-09 20:59:34.621+0000",
      "msgRateIn": 0.0,
      "msgThroughputIn": 0.0,
      "producerId": 0,
      "producerName": "standalone-0-1"
    }
  ],
  "replication": {},
  "storageSize": 16,
  "subscriptions": {
    "my-sub": {
      "blockedSubscriptionOnUnackedMsgs": false,
      "consumers": [
        {
          "address": "/172.17.0.1:35064",
          "availablePermits": 996,
          "blockedConsumerOnUnackedMsgs": false,
          "clientVersion": "1.19.0-incubating",
          "connectedSince": "2017-08-09 21:05:39.222+0000",
          "consumerName": "166111",
          "msgRateOut": 0.0,
          "msgRateRedeliver": 0.0,
          "msgThroughputOut": 0.0,
          "unackedMessages": 0
        }
      ],
      "msgBacklog": 0,
      "msgRateExpired": 0.0,
      "msgRateOut": 0.0,
      "msgRateRedeliver": 0.0,
      "msgThroughputOut": 0.0,
      "type": "Exclusive",
      "unackedMessages": 0
    }
  }
}

至此新一代消息中间件Apache Pulsar架构及实现原理就介绍到这里,更多Apache Pulsar的学习方法可以查看官方文档。#kafka# #Apache Pulsar消息中间件​#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

52it.club

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值