远程调用的核心是在网络服 务层封装了通信协议、序列化、传输等操作,让用户调用远程服务如同进行本地调用一样。 其实,这种方式就是通过网络服务层的封装实现了不同机器上不同进程之间的直接通信,因 为是直接通信,所以通过线程阻塞的方式实现同步调用比较容易,因此通常被用于同步调 用。比如,机器 1 上的进程 A 调用机器 2 上的进程 B,进程 A 被挂起,进程 B 开始执 行,当进程 B 将值返回给 A 时,A 继续执行。虽然这种方式也可以用于异步通信,但因为进程之间是直接交互的,所以当进程比较多时, 会导致进程维护通信的复杂度非常高,且一个进程通信接口改变,与其通信的进程都会受到影响。 随着业务和分布式计算规模的逐渐增大和复杂化,远程调用模型有点心有余力而不足了,为 此出现了专门的异步通信模式,也就是消息发布订阅模式和消息队列模式。
发布订阅的三要素是生产者、消费者和消息中心,生产者负责产生数据放到 消息中心,消费者向消息中心订阅自己感兴趣的消息,当发布者推送数据到消息中心后,消 息中心根据消费者订阅情况将相关数据推送给对应的订阅者。在分布式通信领域中,消息系统一般有两种典型的模式。一种是点对点模式(P2P,Point to Point),另一种是发布订阅模式(Pub/Sub,Publish/Subscribe)。
生产者将消息发送到消息中心,然后消费者从消息中心取出对应的消息进行消费。消息被消 费后,消息中心不再存储该消息,因此其他消费者无法再消费该消息。也就是说,点对点模 式虽然支持多个消费者,但一个消息只能被一个消费者消费,不允许重复消费。
生产者可以发送消息到消息中心,而消息中心通常以主题(Topic)进行划分,每条消息都 会有相应的主题,消息会被存储到自己所属的主题中,订阅该主题的所有消费者均可获得该 消息进行消费。假设生产者 1 发布一个 Topic 相关数据或消息,消费者 1~3 均订阅了该 Topic 消息,则该消息会推送消费者 1~3,也就是说同一个消息被 3 个消费者消费了。
与点对点模式相比,发布订阅模式中一个消息可以被多个消费者进行消费,这也是和点对点 模式的本质区别。
Kafka 是一种典型的发布订阅消息系统,其系统架构也是包括生产者、消费者和消息中心三 部分。
生产者(Producer)负责发布消息到消息中心,比如电子论文的会议方或出版社; 消费者(Consumer)向消息中心订阅自己感兴趣的消息,获得数据后进行数据处理, 比如订阅电子论文的老师或学生; 消息中心(Broker)负责存储生产者发布的消息和管理消费者订阅信息,根据消费者订 阅信息,将消息推送给消费者。在 Kafka 中,消息中心本质上就是一组 服务器,也可以说是 Kafka 集群。
Kafka 中除了 Producer、Broker、Consumer 之外,还有一个 ZooKeeper 集 群。Zookeeper 集群用来协调和管理 Broker 和 Consumer,实现了 Broker 和 Consumer 的解耦,并为系统提供可靠性保证。
ZooKeeper 集群可以看作是一个提供了分布式服务协同能力的第三方组件,Consumer 和 Broker 启动时均会向 ZooKeeper 进行注册,由 ZooKeeper 进行统一管理和协调。 ZooKeeper 中会存储一些元数据信息,比如对于 Broker,会存储主题对应哪些分区 (Partition),每个分区的存储位置等;对于 Consumer,会存储消费组(Consumer Group)中包含哪些 Consumer,每个 Consumer 会负责消费哪些分区等。
Broker 负责存储消息数据,Consumer 负责消费数据, Consumer 消费数据的能力会影响 Broker 数据存储是否溢出的问题。若 Consumer 消费 太慢,会导致 Broker 存储溢出,Broker 就会丢弃一部分消息。 因此,Broker 和 Consumer 是 Kafka 的核心。
在 Kafka 中,为了解决消息存储的负载均衡和系统可靠性问题,所以引入了主题和分区的 概念。其中,主题是一个逻辑概念,指的是消息类型或数据类型。
而分区是针对主题而言的,指的是一个主题的内容可以被划分成多个集合,分布在不同的 Broker 上,不同的 Broker 在不同的节点上。这里的集合就是分区,其中同一个分区只属于一个 Broker。
分区的好处:
实现负载均衡,避免单个 Broker 上的负载过高。比如,Topic 0 被分为 Partiton-0、 Partiton-1 和 Partiton-2 三个分区,分别分布在 Broker 0、Broker 1 和 Broker 2 上。 这,就使得 Topic 0 的消息可以分布在这 3 个分区中,实现负载均衡。 实现消息的备份,从而保证系统的高可靠。比如,Topic 1 包含两个分区 Partiton-0、 Partiton-1,每个分区内容一致,分别存储在 Broker 0 和 Broker 1 上,借此实现了数 据备份。
Kafka 中的消费组,指的是多个消费者的一个集合。一个消费组中的消费者共同消费主题消 息,并且主题中每个消息只可以由消费组中的某一个消费者进行消费。在消息过多的情况下,单个消费者消费能力有限 时,会导致消费效率过低,从而导致 Broker 存储溢出,丢弃一部分消息。Kafka 为了解决 这个问题,所以引入了消费组。
发布订阅模式优点:
1.实现了系统解耦,易于维护。生产者 / 发布者只负责消息的发布,不需要知道订阅者 / 消费者的数量,也不需要知道订阅者 / 消费者获取消息用来做什么,而订阅者 / 消费者 也不需要知道什么时候生产者 / 发布者会发布消息。所以,生产者 / 发布者和订阅者 / 消费者互相独立,进而实现了系统解耦,每个部分可以 单独维护,减少了因为生产者和消费者的耦合引入的一些相互影响。比如,如果两者耦合在 一起,当生产者逻辑更改需要修改代码时,消费者部分的代码也受影响,因此每个部分单独 维护降低了维护的复杂度。
2.实现了异步执行,避免高负载。载。生产者 / 发布者发布消息到消息中心,当消息超过消息 中心可以存储的容量后,消息中心会丢弃掉超出的消息,这样系统就不会因为消息数量 多而导致系统故障。