美文网首页Java
RocketMQ5.0 :NameServer启动流程

RocketMQ5.0 :NameServer启动流程

作者: 喝杯Java润润BUG | 来源:发表于2023-03-15 10:20 被阅读0次

1. NameServer 启动

org.apache.rocketmq.namesrv.NamesrvStartup 的Main函数是启动的入口。

image.png
启动分成了两块:
  1. NameServer启动
  2. Controller启动(5.0为自动自主切换新增的一个模块,内嵌NameServer的时候会启动)

本篇文章只分析NameServer的启动,Controller的启动在后续的文章中进行分析

1.1 命令行参数解析

NameServer启动之前需要先对命令行参数进行解析,将命令行参数解析为NameServer启动需要的参数配置。主要的命令行参数有两个

image.png

-c命令行参数设置配置文件位置,然后将配置文件中的参数值解析设置为配置类的属性值,涉及到的配置有如下几个:

  • NamesrvConfig
  • NettyServerConfig
  • NettyClientConfig
  • ControllerConfig(只有当Controller内嵌NameServer的时候才起作用)
namesrvConfig = new NamesrvConfig();
nettyServerConfig = new NettyServerConfig();
nettyClientConfig = new NettyClientConfig();
nettyServerConfig.setListenPort(9876);
controllerConfig = new ControllerConfig();
if (commandLine.hasOption('c')) {
    String file = commandLine.getOptionValue('c');
    if (file != null) {
        InputStream in = new BufferedInputStream(Files.newInputStream(Paths.get(file)));
        properties = new Properties();
        properties.load(in);
        MixAll.properties2Object(properties, namesrvConfig);
        MixAll.properties2Object(properties, nettyServerConfig);
        MixAll.properties2Object(properties, nettyClientConfig);
        MixAll.properties2Object(properties, controllerConfig);

        namesrvConfig.setConfigStorePath(file);

        System.out.printf("load config properties file OK, %s%n", file);
        in.close();
    }
}

更多的参数设置修改可以参照源码中NamesrvConfig、NettyServerConfig、NettyClientConfig、ControllerConfig中的类属性。

1.2 创建NamesrvController

根据NamesrvController的构造函数创建了三个重要的管理类实例:

  1. KVConfigManager
  2. BrokerHousekeepingService
  3. RouteInfoManager

KVConfigManager KV的持久化、序列化和反序列化处理BrokerHousekeepingService处理客户端和NameServer的连接逻辑,这里的客户端包括:生产者、消费者,以及BrokerRouteInfoManager路由管理,主要管理Broker的元数据,Topic的元数据信息

1.3 初始化NamesrvController

image.png

首先调用NamesrvController#initialize进行初始化,我们看一下初始化做了什么事情。

public boolean initialize() {
        loadConfig();
        initiateNetworkComponents();
        initiateThreadExecutors();
        registerProcessor();
        startScheduleService();
        initiateSslContext();
        initiateRpcHooks();
        return true;
    }

1.3.1 loadConfig

1.3.2 initiateNetworkComponents

private void initiateNetworkComponents() {
    this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.brokerHousekeepingService);
    this.remotingClient = new NettyRemotingClient(this.nettyClientConfig);
}

创建NameServer的网络服务,以及NameServer的客户端。

1.3.3 initiateThreadExecutors

image.png

这里初始化了两个线程池:

  • clientRequestExecutor线程池处理客户端(生产者和消费者)获取Topic的路由信息(RequestCode.GET_ROUTEINFO_BY_TOPIC)
  • defaultExecutor线程池处理除了RequestCode.GET_ROUTEINFO_BY_TOPIC以外的请求。

:::tip 在5.0版本后多了一个clientRequestExecutor线程池,主要是因为增加NameServer的可用性,即使defaultExecutor不能正常工作出现宕机的情况,客户端仍然可以获取Topic的路由信息而进行的线程池的隔离。 具体可以参照[RIP-29] :::

1.3.4 registerProcessor

image.png

将线程池和处理器绑定。 Rocketmq5.0版本对处理器进行了线程池隔离,将获取路由相关的处理和其他的处理例如Broker的注册进行线程池的隔离。

1.3.5 startScheduleService

image.png

启动三个定时任务,两个是打印的的定时任务没有业务逻辑,只有scanNotActiveBroker定时任务的作用:默认每5秒扫描一次Broker是否过期。

1.3.5 initiateSslContext

初始化SsL

1.3.6 initiateRpcHooks

private void initiateRpcHooks() {
    this.remotingServer.registerRPCHook(new ZoneRouteRPCHook());
}

目前只注册了一个ZoneRouteRPCHook,主要用于区域路由。

1.4 启动NamesrvController

public void start() throws Exception {
    this.remotingServer.start();

    // In test scenarios where it is up to OS to pick up an available port, set the listening port back to config
    if (0 == nettyServerConfig.getListenPort()) {
        nettyServerConfig.setListenPort(this.remotingServer.localListenPort());
    }

    this.remotingClient.updateNameServerAddressList(Collections.singletonList(NetworkUtil.getLocalAddress()
        + ":" + nettyServerConfig.getListenPort()));
    this.remotingClient.start();

    if (this.fileWatchService != null) {
        this.fileWatchService.start();
    }

    this.routeInfoManager.start();
}

启动NameServer的Netty对外的服务和客户端服务,在文件监控服务不为空的情况下启动服务。 路由管理服务启动: 主要是启动了批量注销服务。到这里整个服务就已经启动完成。

2. 总结

  1. 启动参数解析:NameServer 启动时需要指定一些参数,例如监听端口、RocketMQ 集群的名称等等。NameServer 会先解析这些参数,并根据这些参数进行初始化。
  2. 加载配置文件:NameServer 还会加载配置文件,包括 broker 配置、路由配置、Topic 配置等等,这些配置文件可以指定在启动参数中,也可以在启动后进行修改。
  3. 创建 MBeanServer:NameServer 还会创建一个 MBeanServer,用于对 NameServer 进行监控和管理。
  4. 启动 Netty 服务端:NameServer 的主要功能是接收 Broker 节点的注册请求和心跳信息,并维护 Broker 节点的状态。为此,NameServer 会启动一个 Netty 服务端,用于接收和处理这些请求。
  5. 注册 ShutdownHook:NameServer 还会注册一个 ShutdownHook,用于在 NameServer 关闭时执行一些清理工作,例如关闭 Netty 服务端、保存路由信息等等。
  6. 初始化定时任务:NameServer 还会初始化一些定时任务,例如定时刷新路由信息、定时清理过期的 Broker 节点等等。这些定时任务是通过 Java 自带的 ScheduledExecutorService 实现的。
  7. 启动完成:最后,NameServer 启动完成,并等待 Broker 节点的注册和心跳信息。
    以上就是 RocketMQ NameServer 的启动流程。需要注意的是,RocketMQ 集群中至少需要一个 NameServer 节点,多个 NameServer 节点可以提高系统的可用性和容错性。

相关文章

网友评论

    本文标题:RocketMQ5.0 :NameServer启动流程

    本文链接:https://www.haomeiwen.com/subject/tldlrdtx.html