Pulsar:下一代消息引擎真的这么强吗?
背景
我们最近在做新业务的技术选型,其中涉及到了对消息中间件的选择;结合我们的实际情况希望它能满足以下几个要求:
- 友好的云原生支持:因为现在的主力语言是
Go
,同时在运维上能够足够简单。 - 官方支持多种语言的
SDK
:还有一些Python
、Java
相关的代码需要维护。 - 最好是有一些方便好用的特性,比如:延时消息、死信队列、多租户等。
当然还有一些水平扩容、吞吐量、低延迟这些特性就不用多说了,几乎所有成熟的消息中间件都能满足这些要求。
基于以上的筛选条件,Pulsar
进入了我们的视野。
作为 Apache
下的顶级项目,以上特性都能很好的支持。
下面我们来它有什么过人之处。
架构
从官方的架构图中可以看出 Pulsar
主要有以下组件组成:
Broker
无状态组件,可以水平扩展,主要用于生产者、消费者连接;与 Kafka 的 broker 类似,但没有数据存储功能,因此扩展更加轻松。BookKeeper
集群:主要用于数据的持久化存储。Zookeeper
用于存储broker
与BookKeeper
的元数据。
整体一看似乎比 Kafka 所依赖的组件还多,这样确实会提供系统的复杂性;但同样的好处也很明显。
Pulsar
的存储于计算是分离的,当需要扩容时会非常简单,直接新增 broker
即可,没有其他的心智负担。
当存储成为瓶颈时也只需要扩容 BookKeeper
,不需要人为的做重平衡,BookKeeper
会自动负载。
同样的操作,Kafka
就要复杂的多了。
特性
多租户
多租户也是一个刚需功能,可以在同一个集群中对不同业务、团队的数据进行隔离。
persistent://core/order/create-order
以这个 topic 名称为例,在 core
这个租户下有一个 order
的 namespace
,最终才是 create-order
的 topic
名称。
在实际使用中租户一般是按照业务团队进行划分,namespace
则是当前团队下的不同业务;这样便可以很清晰的对 topic 进行管理。
通常有对比才会有伤害,在没有多租户的消息中间件中是如何处理这类问题的呢:
- 干脆不分这么细,所有业务线混着用,当团队较小时可能问题不大;一旦业务增加,管理起来会非常麻烦。
- 自己在 topic 之前做一层抽象,但其实本质上也是在实现多租户。
- 各个业务团队各自维护自己的集群,这样当然也能解决问题,但运维复杂度自然也就提高了。
以上就很直观的看出多租户的重要性了。
Function 函数计算
Pulsar
还支持轻量级的函数计算,例如需要对某些消息进行数据清洗、转换,然后再发布到另一个 topic 中。
这类需求就可以编写一个简单的函数,Pulsar
提供了 SDK
可以方便的对数据进行处理,最后使用官方工具发布到 broker
中。
在这之前这类简单的需求可能也需要自己处理流处理引擎。
应用
除此之外的上层应用,比如生产者、消费者这类概念与使用大家都差不多。
比如 Pulsar
支持四种消费模式:
Exclusive
:独占模式,同时只有一个消费者可以启动并消费数据;通过SubscriptionName
标明是同一个消费者),适用范围较小。Failover
故障转移模式:在独占模式基础之上可以同时启动多个consumer
,一旦一个consumer
挂掉之后其余的可以快速顶上,但也只有一个consumer
可以消费;部分场景可用。Shared
共享模式:可以有 N 个消费者同时运行,消息按照round-robin
轮询投递到每个consumer
中;当某个consumer
宕机没有ack
时,该消息将会被投递给其他消费者。这种消费模式可以提高消费能力,但消息无法做到有序。KeyShared
共享模式:基于共享模式;相当于对同一个topic
中的消息进行分组,同一分组内的消息只能被同一个消费者有序消费。
第三种共享消费模式应该是使用最多的,当对消息有顺序要求时可以使用 KeyShared
模式。
SDK
官方支持的 SDK
非常丰富;我也在官方的 SDK
的基础之上封装了一个内部使用的 SDK
。
因为我们使用了 dig 这样的轻量级依赖注入库,所以使用起来大概是这个样子:
SetUpPulsar(lookupURL) container := dig.New() container.Provide(func() ConsumerConfigInstance { return NewConsumer(&pulsar.ConsumerOptions{ Topic: "persistent://core/order/create-order", SubscriptionName: "order-sub", Type: pulsar.Shared, Name: "consumer01", }, ConsumerOrder) }) container.Provide(func() ConsumerConfigInstance { return NewConsumer(&pulsar.ConsumerOptions{ Topic: "persistent://core/order/update-order", SubscriptionName: "order-sub", Type: pulsar.Shared, Name: "consumer02", }, ConsumerInvoice) }) container.Invoke(StartConsumer)
其中的两个 container.Provide()
函数用于注入 consumer
对象。
container.Invoke(StartConsumer)
会从容器中取出所有的 consumer
对象,同时开始消费。
这时以我有限的 Go
开发经验也在思考一个问题,在 Go
中是否需要依赖注入?
先来看看使用 Dig
这类库所带来的好处:
- 对象交由容器管理,很方便的实现单例。
- 当各个对象之前依赖关系复杂时,可以减少许多创建、获取对象的代码,依赖关系更清晰。
同样的坏处也有:
- 跟踪阅读代码时没有那么直观,不能一眼看出某个依赖对象是如何创建的。
- 与 Go 所推崇的简洁之道不符。
对于使用过 Spring
的 Java
开发者来说肯定直呼真香,毕竟还是熟悉的味道;但对于完全没有接触过类似需求的 Gopher
来说貌似也不是刚需。
目前市面上各式各样的 Go 依赖注入库层出不穷,也不乏许多大厂出品,可见还是很有市场的。
我相信有很多 Gopher
非常反感将 Java
中的一些复杂概念引入到 Go
,但我觉得依赖注入本身是不受语言限制,各种语言也都有自己的实现,只是 Java 中的 Spring 不仅仅只是一个依赖注入框架,还有许多复杂功能,让许多开发者望而生畏。
如果只是依赖注入这个细分需求,实现起来并不复杂,并不会给带来太多复杂度。如果花时间去看源码,在理解概念的基础上很快就能掌握。
回到 SDK
本身来说,Go
的 SDK
现阶段要比 Java
版本的功能少(准确来说只有 Java
版的功能最丰富),但核心的都有了,并不影响日常使用。
总结
本文介绍了 Pulsar
的一些基本概念与优点,同时顺便讨论一下 Go
的依赖注入;如果大家和我们一样在做技术选型,不妨考虑一下 Pulsar
。
后续会继续分享 Pulsar 的相关内容,有相关经验的朋友也可以在评论区留下自己的见解。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
为什么Kafka在2.8版本中会“抛弃”Zookeeper,选择拥抱Raft?
相信大家最近一定关注到一款重量级消息中间件Kafka发布了2.8版本,并且正式移除了对Zookeeper的依赖,背后的设计哲学是什么呢?仅仅只是减少了一个外部依赖吗? 答案显然不会这么简单,容我慢慢道来。 在解答为什么之前,我觉得非常有必要先来阐述一下Zookeeper的经典使用场景。 1、Zookeeper的经典使用场景 zookeeper是伴随着大数据、分布式领域的兴起。大数据中的一个非常重要的议题是如何使用众多廉价的机器来实现可靠存储。 所谓廉价的机器就是发生故障的概率非常大,但单台的成本也非常低,分布式领域希望使用多台机器组成一个集群,将数据存储在多台机器上(副本),为了方便实现数据一致性,通常需要从一个复制组中挑选一台主节点用户处理数据的读写,其他节点从主节点拷贝数据,当主节点宕机,需要自动进行重新选举,实现高可用。 上述场景中有一个非常重要的功能Leader选举,如何选举出一个主节点、并支持主节点宕机后自动触发重新选举,实现主从自动切换,实现高可用。 使用Zookeeper提供的临时顺序节点与事件监听机制,能非常轻松的实现Leader选举。 上面的t1,t2可以理解为一个组...
- 下一篇
用面向对象解决「夜过吊桥」问题~
问题描述 1.五个人打算过一座吊桥,开始时他们都位于该桥的一侧。 2.天很黑,五个人手里只有一个手电筒。 3.该桥一次最多只能同时过两个人,无论是一个人还是两个人过桥,都需要携带手电筒看路。而且手电筒只能通过人携带过桥的方式传递。 4.第一个人过桥需要1分钟时间,第二个人过桥需要2分钟,第三个人需要5分钟,第四个需要7分钟,第五个需要10分钟。由于速度不同,两个人一起过桥的话,速度以慢的人为准。 问题:求最快过桥时间。要求写出求解的算法。 分析题目 1.从左边到右边,需要有一个人拿着手电筒,到达右边后,需要有一个人折返回到左边,那么怎么才能最大化的减少返回时间? 答:那么这个送回手电筒的人一定是右边最快的。 2.两人同时过桥,取最大时间,那怎么才能保证最大化的利用最长时间呢? 答:在左边选最长时间的两个人一起过桥。 3.怎么保证右边折返回来回左边的人所花的时间最短? 答:左边选择最快的两个人一起到右边,然后最快的折返回左边,次快的等待最慢的两个人过来后,再折返回左边。重复这个步骤即可保证折返回左边的人所花的时间最短。 我们来试着算一下,最短需要多长时间。 (1)选择左边最快的两个...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL8.0.19开启GTID主从同步CentOS8
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案