rocketMQ学习笔记——broker的启动和高可用服务

broker

本文仅仅探讨broker的启动和高可用注册, 以及如何提供消息服务

这里有一个不理解的地方就是, broker的高可用服务并没有使用到netty, 而是使用了NIO的socket

broker就是个代理商, 生产者的消息发送给broker后, 消费者再去broker上面拉消息

rocketMQ的broker有高可用机制, 可以主从复制然后slave broker可以提供消息读取服务

主从broker的区别在于注册进namesrv的时候master的brokerId是0而slave的brokerId是1

namesrv会判断broker的brokerId来判断是否设置masterAddr

slave会根据这个masterAddr与master建立一个socket连接, 根据偏移量来拉取消息备份到自己的服务器上

controller

broker与namesrv一样也是通过controller来启动服务的

在broker的启动类中main方法先创建了controller然后再调用start方法启动controller

下面只提取一些重要部分代码

    public static BrokerController createBrokerController(String[] args) {
   
        System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, Integer.toString(MQVersion.CURRENT_VERSION));

        try {
   
            //PackageConflictDetect.detectFastjson();
            Options options = ServerUtil.buildCommandlineOptions(new Options());
            commandLine = ServerUtil.parseCmdLine("mqbroker", args, buildCommandlineOptions(options),
                new PosixParser());
            if (null == commandLine) {
   
                System.exit(-1);
            }

            final BrokerConfig brokerConfig = new BrokerConfig();
            final NettyServerConfig nettyServerConfig = new NettyServerConfig();
            final NettyClientConfig nettyClientConfig = new NettyClientConfig();

            nettyClientConfig.setUseTLS(Boolean.parseBoolean(System.getProperty(TLS_ENABLE,
                String.valueOf(TlsSystemConfig.tlsMode == TlsMode.ENFORCING))));
            nettyServerConfig.setListenPort(10911);
            // messageStore用于消息的存放与处理
            final MessageStoreConfig messageStoreConfig = new MessageStoreConfig();

            if (BrokerRole.SLAVE == messageStoreConfig.getBrokerRole()) {
   
                int ratio = messageStoreConfig.getAccessMessageInMemoryMaxRatio() - 10;
                messageStoreConfig.setAccessMessageInMemoryMaxRatio(ratio);
            }

            // 读取配置中设置的配置文件地址, 并且加载成javaBean
            if (commandLine.hasOption('c')) {
   
                String file = commandLine.getOptionValue('c');
                if (file != null) {
   
                    configFile = file;
                    InputStream in = new BufferedInputStream(new FileInputStream(file));
                    properties = new Properties();
                    properties.load(in);

                    properties2SystemEnv(properties);
                    MixAll.properties2Object(properties, brokerConfig);
                    MixAll.properties2Object(properties, nettyServerConfig);
                    MixAll.properties2Object(properties, nettyClientConfig);
                    MixAll.properties2Object(properties, messageStoreConfig);

                    BrokerPathConfigHelper.setBrokerConfigPath(file);
                    in.close();
                }
            }

            MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), brokerConfig);
            // rocketMQHome是必须设置的配置
            if (null == brokerConfig.getRocketmqHome()) {
   
                System.out.printf("Please set the %s variable in your environment to match the location of the RocketMQ installation", MixAll.ROCKETMQ_HOME_ENV);
                System.exit(-2);
            }
            // namesrv地址也是配置在配置文件中的
            String namesrvAddr = brokerConfig.getNamesrvAddr();
            if (null != namesrvAddr) {
   
                try {
   
                    // 获取名称服务地址, 配置中多地址用分号;分割
                    String[] addrArray = namesrvAddr.split(";");
                    for (String addr : addrArray) {
   
                        RemotingUtil.string2SocketAddress(addr);
                    }
                } catch (Exception e) {
   
                    System.out.printf(
                        "The Name Server Address[%s] illegal, please set it as follows, \"127.0.0.1:9876;192.168.0.1:9876\"%n",
                        namesrvAddr);
                    System.exit(-3);
                }
            }

            switch (messageStoreConfig.getBrokerRole()) {
   
                // 主服务都要设置brokerId
                case ASYNC_MASTER:
                case SYNC_MASTER:
                    brokerConfig.setBrokerId(MixAll.MASTER_ID);
                    break;
                // 从服务的brokerId不能小于等于0
                // 所以slave的brokerId可以是1以上的任何数字
                case SLAVE:
                    if (brokerConfig.getBrokerId() <= 0) {
   
                        System.out.printf("Slave's brokerId must be > 0");
                        System.exit(-3);
                    }

                    break;
                default:
                    break;
            }

            if (messageStoreConfig.isEnableDLegerCommitLog()) {
   
                brokerConfig.setBrokerId(-1);
            }
            // 设置高可用的端口, 默认是netty服务端端口+1
            messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);
		   // 省略日志

            // 根据设置的config创建broker
            final BrokerController controller = new BrokerController(
                brokerConfig,
                nettyServerConfig,
                nettyClientConfig,
                messageStoreConfig);
            // remember all configs to prevent discard
            controller.getConfiguration().registerConfig(properties);
            // 对controller进行初始化
            boolean initResult = controller.initialize();
            if (!initResult) {
   
                controller.shutdown();
                System.exit(-3);
            }

            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
   
                private volatile boolean hasShutdown = false;
                private AtomicInteger shutdownTimes = new AtomicInteger(0);

                @Override
                public void run() {
   
                    synchronized (this) {
   
                        log.info("Shutdown hook was invoked, {}", this.shutdownTimes.incrementAndGet());
                        if (!this.hasShutdown) {
   
                            this.hasShutdown = true;
                            long beginTime = System.currentTimeMillis();
                            controller.shutdown();
                            long consumingTimeTotal = System.currentTimeMillis() - beginTime;
                            log.info("Shutdown hook over, consuming total time(ms): {}", consumingTimeTotal);
                        }
                    }
                }
            }, "ShutdownHook"));

            return controller;
        } catch (Throwable e) {
   
            e.printStackTrace();
            System.exit(-1);
        }

        return null;
    }

其中最重要的部分就是controller的初始化

初始化中创建了netty相关的服务, 初始化了rocketMQ支持的事务消息和消息确认, 并且注册了rpc的钩子函数, 注册了netty事件的处理器

加载了消息仓库, messageStore中启动了commitLog和messageQueue

public boolean initialize() throws CloneNotSupportedException {
   
        boolean result = this.topicConfigManager.load();

        result = result && this.consumerOffsetManager.load();
        result = result && this.subscriptionGroupManager.load();
        result = result && this.consumerFilterManager.load();

        if (result) {
   
            try {
   
                // 创建消息存储仓库
                this.messageStore =
                    new DefaultMessageStore(this.messageStoreConfig, this.brokerStatsManager, this.messageArrivingListener,
                        this.brokerConfig);
                if (messageStoreConfig.isEnableDLegerCommitLog()) {
   
                    DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore);
                    ((DLedgerCommitLog)((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值