• RocketMQ源码 — 二、 NameServer


    NameServer

    作用:Producer和Consumer获取Broker的地址
    目的:解耦Broker和Producer、Consumer
    原理:使用netty作为通信工具,监听指定端口,如果是broker注册,将broker的信息保存在内存中并保存到文件中,producer和consumer获取broker地址的请求

    RocketMQ包含的组件

    • NameServer:单点,供Producer和Consumer获取Broker地址
    • Producer:产生并发送消息
    • Consumer:接受并消费消息
    • Broker:消息暂存,消息转发

    NamesrvController包含的组件

    • namesrvConfig:nameServer的配置
    • nettyServerConfig:NameServer的netty配置
    • remotingServer:NameServer 的netty服务器
    • scheduledExecutorService:routeInfoManager和kvCOnfigManager使用的定时线程池
    • remotingExecutor:netty使用的线程池
    • brokerHosekeppingService:
    • kvConfigManager:kv配置管理
    • routeInfoManager:包含broker的ip和对应的队列信息,说明producer可以往哪一个broker发送消息,consumer从哪一个broker pull消息

    NameServer启动

    NamesrvStartup.main0

    1. NettySystemConfig配置
    2. 解析命令行参数,NettyServerConfig配置
    3. logback配置
    4. NamesrvController初始化,initialize
    5. 注册shutdown钩子
    6. NamesrvController.start

    NamesrvController.initialize

    1. KVConfigManager.load加载原来的key-value文件到内存中
    2. 初始化NettyRemotingServer
    3. 注册requestProcessor,默认为DefaultRequestProcessor,用来处理netty接收到的信息
    4. 启动定时线程,每隔10s判断broker是否依然存活
    5. 启动定时线程,每隔10min打印出所有k-v

    NamesrvController.start

    启动netty server,使用NettyServerHandler进行read和write,最终调用到DefaultRequestProcessor.processRequest

    NameServer处理信息

    netty收到的所有消息都是DefaultRequestProcessor.processRequest处理的,根据不同的RequestCode执行不同的操作

    public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
        if (log.isDebugEnabled()) {
            log.debug("receive request, {} {} {}",//
                    request.getCode(), //
                    RemotingHelper.parseChannelRemoteAddr(ctx.channel()), //
                    request);
        }
    
        switch (request.getCode()) {
            case RequestCode.PUT_KV_CONFIG:
                return this.putKVConfig(ctx, request);
            case RequestCode.GET_KV_CONFIG:
                return this.getKVConfig(ctx, request);
            case RequestCode.DELETE_KV_CONFIG:
                return this.deleteKVConfig(ctx, request);
            case RequestCode.REGISTER_BROKER:	// 注册borker信息
                Version brokerVersion = MQVersion.value2Version(request.getVersion());
                if (brokerVersion.ordinal() >= MQVersion.Version.V3_0_11.ordinal()) {
                    return this.registerBrokerWithFilterServer(ctx, request);
                }
                else {
                    return this.registerBroker(ctx, request);
                }
            case RequestCode.UNREGISTER_BROKER:		// 取消注册broker
                return this.unregisterBroker(ctx, request);
            case RequestCode.GET_ROUTEINTO_BY_TOPIC:
                return this.getRouteInfoByTopic(ctx, request);		// 根据topic获取路由信息,在producer发送消息和consumer在pull消息的时候的时候会从nameServer 中获取
            case RequestCode.GET_BROKER_CLUSTER_INFO:
                return this.getBrokerClusterInfo(ctx, request);
            case RequestCode.WIPE_WRITE_PERM_OF_BROKER:
                return this.wipeWritePermOfBroker(ctx, request);
            case RequestCode.GET_ALL_TOPIC_LIST_FROM_NAMESERVER:
                return getAllTopicListFromNameserver(ctx, request);
            case RequestCode.DELETE_TOPIC_IN_NAMESRV:
                return deleteTopicInNamesrv(ctx, request);
            case RequestCode.GET_KVLIST_BY_NAMESPACE:
                return this.getKVListByNamespace(ctx, request);
            case RequestCode.GET_TOPICS_BY_CLUSTER:
                return this.getTopicsByCluster(ctx, request);
            case RequestCode.GET_SYSTEM_TOPIC_LIST_FROM_NS:
                return this.getSystemTopicListFromNs(ctx, request);
            case RequestCode.GET_UNIT_TOPIC_LIST:
                return this.getUnitTopicList(ctx, request);
            case RequestCode.GET_HAS_UNIT_SUB_TOPIC_LIST:
                return this.getHasUnitSubTopicList(ctx, request);
            case RequestCode.GET_HAS_UNIT_SUB_UNUNIT_TOPIC_LIST:
                return this.getHasUnitSubUnUnitTopicList(ctx, request);
            default:
                break;
        }
        return null;
    }
    

    这里主要看注册broker,依次调用DefaultRequestProcessor.registerBroker->RouteInfoManager.registerBroker;
    进行的主要操作是解析request,依次填充以下集合,供producer和consumer获取

    // 某一个topic对应的逻辑队列
    private final HashMap<String/* topic */, List<QueueData>> topicQueueTable;
    // 每个broker 对应的信息
    private final HashMap<String/* brokerName */, BrokerData> brokerAddrTable;
    // 某一个集群下对应的所有broker
    private final HashMap<String/* clusterName */, Set<String/* brokerName */>> clusterAddrTable;
    private final HashMap<String/* brokerAddr */, BrokerLiveInfo> brokerLiveTable;
    // 某一个broker对应的filter
    private final HashMap<String/* brokerAddr */, List<String>/* Filter Server */> filterServerTable;
    
  • 相关阅读:
    vue3 祖孙传递数据
    vue 导航栏不能收缩的问题
    vue 项目中的问题
    Python第一周Round1记录
    [转]80端口被系统占用pid=4: NT kernel & System
    表<表名称> 中的列与现有的主键或UNIQUE约束不匹配
    一些算法(2)
    卸载不了java(tm)se development kit 7 update 3
    如何解决 Eclipse中出现访问限制由于对必需的库XX具有一定限制,因此无法访问类型
    [COPY]Eclipse无法导入项目
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/6287404.html
Copyright © 2020-2023  润新知