Pulsar是一款非常优秀的消息流平台,这篇文章主要讲Pulsar中Topic通过Bundle这个负载均衡利器在Broker中的分配。
1 Topic层级概念
首先看一下Pulsar的架构图,如下图:
Pulsar的Broker可以管理一个或者多个Topic。Pulsar是一个多租户平台,多租户的特性体现在Topic是一个层级概念,Topic的URL如下图:
一个Topic可以使用persistent属性指定是否持久化,而Topic的上层使用租户来进行权限隔离,使用Namespace来进行策略管理。
Topic的层级概念也可以用下图来表示:
在一个公司内部的Pulsar集群中,可以根据业务部门建租户,根据业务部门内部的不同项目组来划分Namespace,根据每个项目组的不同业务单元来划分Topic。
2 Namespace Bundles
Pulsar把Namespace拆成了Bundle,Bundle是namespace的子集。如下图一个Namespace下面有6个Topic:
我们把这个Namespace划分成四个hash区域,从0x00000000~0xffffffff,之后把6个Topic按照名字(上面URL图中的最后一部分)做Hash运算,分配到这四个区域内,如下图:
上图中,Topic0做Hash运算后值落在了0xc0000000~0xffffffff这个区域,其他几个Topic也分别落到了自己的Hash区域。
为什么要为Namespace划分Bundle子集呢?因为Pulsar有自动负载均衡机制,会把繁忙的Broker里面的一些Topic迁移到比较空闲的Broker中,实现Broker直接的流量均衡。这个搬移如果直接搬移Namespace,会太重,比如上面的图需要一下子搬移6个Topic。如果以Topic为单位,每次搬移数据就会太小,而且搬移过程中需要保存大量Topic和Broker之间的元数据。有了Bundle后,以Bundle为单位进行迁移,迁移Topic会容易很多,比如上图中,一次迁移一个Bundle,有的包含一个Topic,有的包含两个Topic。
3 Broker分配Bundle
Broker集群启动过程中会在Zookeeper竞争创建临时节点,创建成功的成为Leader节点,叫Load Manager,这个节点会定期搜集其他Broker的服务状态,比如CPU、内存、网卡带宽利用率,这些指标都是临时数据,所以Leader节点并不会保存太多数据。
Leader节点会根据搜集到的负载情况为其他Broker节点分配Bundle。如下图:
上图中Broker1竞争成为Leader,它负责为其他几个Broker分配Bundle。初始化时,每个Broker都没有Boundle,Leader把topic0分配给了Broker3,这就代表topic0所在的Bundle分配给了Broker3,之后Hash值跟topic0相同的都会落到这个Bundle。然后把topic1分配给了Broker2,这就代表topic1所在的Bundle分配给了Broker2。类似把其他2个Bundle分别分配给了Broker0和Broker1。
4 高可用
还是以上面的图为例,如果Broker0宕机了,Load Manager和ZK都能检测到broker0宕机,这时Load Manager会重新把Bundle(0x00000000~0x400000000)分配给其他三个broker,最后选择哪个broker取决于Load Manager收集到的每个broker的负载情况,会找一个负载最小的broker分配。如下图:
如果Broker1宕机了,也就是Leader节点宕机了,那Broker0、Broker1和Broker2三个节点会去Zookeeper抢占注册零时节点,注册成功的成为新的Leader,新的Leader节点会把Broker1的Bundle分配给剩下的3个Broker。
5 客户端
Topic通过Bundle绑定了Broker之后,客户端就可以跟自己要访问的Broker建立长链接,如下图:
这里需要注意:图中的第1、2两步既可以用HTTP的方式,也可以用TCP的方式,但是第3步也就是Broker跟client建立连接只能用TCP。
Pulsar为客户端提供了代理,客户端可以直接跟代理通信,如下图:
6 总结
使用了Bundle,Pulsar可以方便地通过Load Manager节点做负载均衡,不用考虑一次搬移的Topic太多,也不用担心一次搬移一个Topic而需要保存太多元数据。