1. 为什么 RocketMQ 要自己做一个 NameServer, 而不使用现成的 Zookeeper、Nacos、Eureka 这些服务注册中心,NameServer 挂了,RocketMQ 还能正常工作吗 ?
NameServer 本质上就是给 broker 做注册用的,把自己所有的信息都放到服务端,然后供客户端去调用,那么它自己做一个 NameServer 就是用来解决版本依赖,不依赖于外部的组件呗,其实不然;它有更深层次的原因:
1. 独立运行的分散结构
NameServer 节点与节点之间是独立工作的,没有任何的数据交互。那么每个节点就会持有全量的 Broker 数据。这就意味着只要有任意一台 NameServer 正常工作,整个客户端和 Broker 集群就可以正常运行。而 Nacos、zookeeper 等服务注册中心需要超过半数节点正常运行才能提供服务,所以 NameServer 具有更好的高可用性;
2. 简化实现,容忍部分数据不一致
由于 NameServer 节点之间没有交互,因此数据无法同步,就可能会出现 Broker 集群在一些 NameServer 上注册成功,在另一些 NameServer 上注册失败的情况。就会导致 Broker 列表数据不一致问题。然而,在 RocketMQ 中这是一种可接受的状态。客户端只要能找到一个可用的 Broker 就可以正常工作。相比之下,像 Nacos 和 Zookeeper 等服务注册中心,它们是不容许这种不一致性的存在。基于这样的设计,那么 NameServer 就可以放大数据不一致的缺点,从而让 NameServer 的实现更加简单清晰。
NameServer 服务挂了,只要还有一个可用的 broker ,RocketMQ 就还能工作!
2. RocketMQ 5.x 版本中,proxy、controller 和 container 分别有什么用 ?
⭐ Proxy:多语言支持、简化开发
在 RocketMQ 早期版本中,客户端和 Broker 通过 Netty 协议进行通讯,这是一个基于 Java 的网络库。由于 Netty 主要支持 Java 语言,这使得非 Java 语言的客户端与 Broker 的通讯就变得困难。所以 RocketMQ 5.x 版本,就在 Broker 上加了一个代理层 Proxy,相当于在网络层增加一个 GRPC 的服务端,这样 Broker 就能支持更多语言版本的客户端了。
⭐ Controller: 提高 Broker 的性能
在 RocketMQ 4.x 版本中,提供了两种集群方式:普通的主从集群和 DLedger 集群。DLedger 集群有一个好处是,当主节点挂掉后,剩余的节点可以自行选举新的主节点。然而这种集群方式又要求选举后节点的日志存储格式,必须按照 Dledger 那种格式来做,这样就需要保证集群内的数据一致性,就需要发各种请求,各种各样的同步,就肯定会影响性能,所以 RocketMQ5.x 版本,就在 NameServer 上增加了一个独立的 controller 层,门用来管理节点的选举,每一个 broker 节点依然按照自己原来的存储方式去存储数据就行了。
⭐ Container:提高资源利用率,平衡负载
在 RocketMQ 4.x 版本中,针对 Broker 的每一个主从集群,他们都是作为一个独立的进程部署在服务器上的,那么这些进程的负载情况就会非常不合理,master 节点上需要处理很多的请求,而 slaver 节点不需要处理客户端的请求,只需要针对 master 做数据同步,这样就会导致集群的性能没办法充分发挥,所以在 RocketQM5.x 版本中引入了 container 组件,它可以允许在一个进程内部署多个 Broker 实例(master,slaver),相当于将多个服务器进程合并到了一个进程,这样服务器的性能就得到更加均衡的分配了。