第一章 NameServer

来源:互联网 发布:剑三mmd花萝捏脸数据 编辑:程序博客网 时间:2024/06/09 20:58

一、NameServer

    NameServer包下面总共就三个模块

1、kvconfig模块

    处理key,value类型的配置,目前只使用了了ORDER_TOPIC_CONFIG key

2、processor模块

    处理来自consumer,producer,broker的请求

3、routeinfo模块

    处理broker集群信息,broker与topic, topic的队列信息

二、功能整合

1、NamesrvController

    整合三个模块的功能,通过NettyServer客户端提供服务

2、NamesrvStartup

    加载NettyServerConfig与NameSrvConfig,其中采用apache cli框架读取命令行参数的方式来加载配置,这种配置文件加载方式能够有效隔离不同环境配置。启动服务。

三 按模块分析

1.kvconfig

KVConfigManager

kv属性管理

KVConfigSerializeWrapper

kv属性序列化增强

2.processor模块

DefaultRequestProcessor

默认请求处理,处理来自C,P,B 的请求,维护与broker的心跳处理的请求类型:

ClusterTestRequestProcessor

集群模式请求处理 继承与上面的,在取不到topic的时候去admin取,这是唯一的区别

3.routeinfo模块

BrokerHousekeepingService

broker链接保持服务

RouteInfoManager

路由信息管理,通过读写锁控制信息。主要来分析一下其中的方法

RouteInfoManager字段

  private final ReadWriteLock lock = new ReentrantReadWriteLock();    private final HashMap<String/* topic */, List<QueueData>> topicQueueTable;    private final HashMap<String/* brokerName */, BrokerData> brokerAddrTable;    private final HashMap<String/* clusterName */, Set<String/* brokerName */>> clusterAddrTable;    private final HashMap<String/* brokerAddr */, BrokerLiveInfo> brokerLiveTable;    private final HashMap<String/* brokerAddr */, List<String>/* Filter Server */> filterServerTable;
    1.lock,用来保护的读写锁    2.topicQueueTable,根据topic存储topic对应的queue的关系    3.brokerAddrTable根据brokerName存储broker的addr和cluster信息    4.brokerLiveTable存放broker的存活信息    5.filterServerTable存放filtersrc信息

RouteInfoManager方法

1.获取所有集群的信息(无锁)
public byte[] getAllClusterInfo() {        ClusterInfo clusterInfoSerializeWrapper = new ClusterInfo();        clusterInfoSerializeWrapper.setBrokerAddrTable(this.brokerAddrTable);        clusterInfoSerializeWrapper.setClusterAddrTable(this.clusterAddrTable);        return clusterInfoSerializeWrapper.encode();    }
2.删除topic信息(需要写锁)
    public void deleteTopic(final String topic) {        try {            try {                this.lock.writeLock().lockInterruptibly();                this.topicQueueTable.remove(topic);            } finally {                this.lock.writeLock().unlock();            }        } catch (Exception e) {            log.error("deleteTopic Exception", e);        }    }
3.获取所有broker的topicList(读锁)
    public byte[] getAllTopicList() {        TopicList topicList = new TopicList();        try {            try {                this.lock.readLock().lockInterruptibly();                topicList.getTopicList().addAll(this.topicQueueTable.keySet());            } finally {                this.lock.readLock().unlock();            }        } catch (Exception e) {            log.error("getAllTopicList Exception", e);        }        return topicList.encode();    }
4.注册broker(写锁)0
    public RegisterBrokerResult registerBroker(        final String clusterName,        final String brokerAddr,        final String brokerName,        final long brokerId,        final String haServerAddr,        final TopicConfigSerializeWrapper topicConfigWrapper,        final List<String> filterServerList,        final Channel channel) {        RegisterBrokerResult result = new RegisterBrokerResult();        try {            try {                this.lock.writeLock().lockInterruptibly();                Set<String> brokerNames = this.clusterAddrTable.get(clusterName);                if (null == brokerNames) {                    brokerNames = new HashSet<String>();                    this.clusterAddrTable.put(clusterName, brokerNames);                }                brokerNames.add(brokerName);                boolean registerFirst = false;                BrokerData brokerData = this.brokerAddrTable.get(brokerName);                if (null == brokerData) {                    registerFirst = true;                    brokerData = new BrokerData(clusterName, brokerName, new HashMap<Long, String>());                    this.brokerAddrTable.put(brokerName, brokerData);                }                String oldAddr = brokerData.getBrokerAddrs().put(brokerId, brokerAddr);                registerFirst = registerFirst || (null == oldAddr);                if (null != topicConfigWrapper                    && MixAll.MASTER_ID == brokerId) {                    if (this.isBrokerTopicConfigChanged(brokerAddr, topicConfigWrapper.getDataVersion())                        || registerFirst) {                        ConcurrentMap<String, TopicConfig> tcTable =                            topicConfigWrapper.getTopicConfigTable();                        if (tcTable != null) {                            for (Map.Entry<String, TopicConfig> entry : tcTable.entrySet()) {                                this.createAndUpdateQueueData(brokerName, entry.getValue());                            }                        }                    }                }                BrokerLiveInfo prevBrokerLiveInfo = this.brokerLiveTable.put(brokerAddr,                    new BrokerLiveInfo(                        System.currentTimeMillis(),                        topicConfigWrapper.getDataVersion(),                        channel,                        haServerAddr));                if (null == prevBrokerLiveInfo) {                    log.info("new broker registerd, {} HAServer: {}", brokerAddr, haServerAddr);                }                if (filterServerList != null) {                    if (filterServerList.isEmpty()) {                        this.filterServerTable.remove(brokerAddr);                    } else {                        this.filterServerTable.put(brokerAddr, filterServerList);                    }                }                if (MixAll.MASTER_ID != brokerId) {                    String masterAddr = brokerData.getBrokerAddrs().get(MixAll.MASTER_ID);                    if (masterAddr != null) {                        BrokerLiveInfo brokerLiveInfo = this.brokerLiveTable.get(masterAddr);                        if (brokerLiveInfo != null) {                            result.setHaServerAddr(brokerLiveInfo.getHaServerAddr());                            result.setMasterAddr(masterAddr);                        }                    }                }            } finally {                this.lock.writeLock().unlock();            }        } catch (Exception e) {            log.error("registerBroker Exception", e);        }        return result;    }    private boolean isBrokerTopicConfigChanged(final String brokerAddr, final DataVersion dataVersion) {        BrokerLiveInfo prev = this.brokerLiveTable.get(brokerAddr);        if (null == prev || !prev.getDataVersion().equals(dataVersion)) {            return true;        }        return false;    }
5.创建或者更新队列信息,由更新broker方法调用
    private void createAndUpdateQueueData(final String brokerName, final TopicConfig topicConfig) {        QueueData queueData = new QueueData();        queueData.setBrokerName(brokerName);        queueData.setWriteQueueNums(topicConfig.getWriteQueueNums());        queueData.setReadQueueNums(topicConfig.getReadQueueNums());        queueData.setPerm(topicConfig.getPerm());        queueData.setTopicSynFlag(topicConfig.getTopicSysFlag());        List<QueueData> queueDataList = this.topicQueueTable.get(topicConfig.getTopicName());        if (null == queueDataList) {            queueDataList = new LinkedList<QueueData>();            queueDataList.add(queueData);            this.topicQueueTable.put(topicConfig.getTopicName(), queueDataList);            log.info("new topic registerd, {} {}", topicConfig.getTopicName(), queueData);        } else {            boolean addNewOne = true;            Iterator<QueueData> it = queueDataList.iterator();            while (it.hasNext()) {                QueueData qd = it.next();                if (qd.getBrokerName().equals(brokerName)) {                    if (qd.equals(queueData)) {                        addNewOne = false;                    } else {                        log.info("topic changed, {} OLD: {} NEW: {}", topicConfig.getTopicName(), qd,                            queueData);                        it.remove();                    }                }            }            if (addNewOne) {                queueDataList.add(queueData);            }        }    }
6.擦除指定broker的topic的写权限(写锁)
    public int wipeWritePermOfBrokerByLock(final String brokerName) {        try {            try {                this.lock.writeLock().lockInterruptibly();                return wipeWritePermOfBroker(brokerName);            } finally {                this.lock.writeLock().unlock();            }        } catch (Exception e) {            log.error("wipeWritePermOfBrokerByLock Exception", e);        }        return 0;    }    private int wipeWritePermOfBroker(final String brokerName) {        int wipeTopicCnt = 0;        Iterator<Entry<String, List<QueueData>>> itTopic = this.topicQueueTable.entrySet().iterator();        while (itTopic.hasNext()) {            Entry<String, List<QueueData>> entry = itTopic.next();            List<QueueData> qdList = entry.getValue();            Iterator<QueueData> it = qdList.iterator();            while (it.hasNext()) {                QueueData qd = it.next();                if (qd.getBrokerName().equals(brokerName)) {                    int perm = qd.getPerm();                    perm &= ~PermName.PERM_WRITE;                    qd.setPerm(perm);                    wipeTopicCnt++;                }            }        }        return wipeTopicCnt;    }
7.注销broker(写锁)
    public void unregisterBroker(        final String clusterName,        final String brokerAddr,        final String brokerName,        final long brokerId) {        try {            try {                this.lock.writeLock().lockInterruptibly();                BrokerLiveInfo brokerLiveInfo = this.brokerLiveTable.remove(brokerAddr);                log.info("unregisterBroker, remove from brokerLiveTable {}, {}",                    brokerLiveInfo != null ? "OK" : "Failed",                    brokerAddr                );                this.filterServerTable.remove(brokerAddr);                boolean removeBrokerName = false;                BrokerData brokerData = this.brokerAddrTable.get(brokerName);                if (null != brokerData) {                    String addr = brokerData.getBrokerAddrs().remove(brokerId);                    log.info("unregisterBroker, remove addr from brokerAddrTable {}, {}",                        addr != null ? "OK" : "Failed",                        brokerAddr                    );                    if (brokerData.getBrokerAddrs().isEmpty()) {                        this.brokerAddrTable.remove(brokerName);                        log.info("unregisterBroker, remove name from brokerAddrTable OK, {}",                            brokerName                        );                        removeBrokerName = true;                    }                }                if (removeBrokerName) {                    Set<String> nameSet = this.clusterAddrTable.get(clusterName);                    if (nameSet != null) {                        boolean removed = nameSet.remove(brokerName);                        log.info("unregisterBroker, remove name from clusterAddrTable {}, {}",                            removed ? "OK" : "Failed",                            brokerName);                        if (nameSet.isEmpty()) {                            this.clusterAddrTable.remove(clusterName);                            log.info("unregisterBroker, remove cluster from clusterAddrTable {}",                                clusterName                            );                        }                    }                    this.removeTopicByBrokerName(brokerName);                }            } finally {                this.lock.writeLock().unlock();            }        } catch (Exception e) {            log.error("unregisterBroker Exception", e);        }    }    private void removeTopicByBrokerName(final String brokerName) {        Iterator<Entry<String, List<QueueData>>> itMap = this.topicQueueTable.entrySet().iterator();        while (itMap.hasNext()) {            Entry<String, List<QueueData>> entry = itMap.next();            String topic = entry.getKey();            List<QueueData> queueDataList = entry.getValue();            Iterator<QueueData> it = queueDataList.iterator();            while (it.hasNext()) {                QueueData qd = it.next();                if (qd.getBrokerName().equals(brokerName)) {                    log.info("removeTopicByBrokerName, remove one broker's topic {} {}", topic, qd);                    it.remove();                }            }            if (queueDataList.isEmpty()) {                log.info("removeTopicByBrokerName, remove the topic all queue {}", topic);                itMap.remove();            }        }    }
8.根据topic获取broker,filter,以及queue信息
    public TopicRouteData pickupTopicRouteData(final String topic) {        TopicRouteData topicRouteData = new TopicRouteData();        boolean foundQueueData = false;        boolean foundBrokerData = false;        Set<String> brokerNameSet = new HashSet<String>();        List<BrokerData> brokerDataList = new LinkedList<BrokerData>();        topicRouteData.setBrokerDatas(brokerDataList);        HashMap<String, List<String>> filterServerMap = new HashMap<String, List<String>>();        topicRouteData.setFilterServerTable(filterServerMap);        try {            try {                this.lock.readLock().lockInterruptibly();                List<QueueData> queueDataList = this.topicQueueTable.get(topic);                if (queueDataList != null) {                    topicRouteData.setQueueDatas(queueDataList);                    foundQueueData = true;                    Iterator<QueueData> it = queueDataList.iterator();                    while (it.hasNext()) {                        QueueData qd = it.next();                        brokerNameSet.add(qd.getBrokerName());                    }                    for (String brokerName : brokerNameSet) {                        BrokerData brokerData = this.brokerAddrTable.get(brokerName);                        if (null != brokerData) {                            BrokerData brokerDataClone = new BrokerData(brokerData.getCluster(), brokerData.getBrokerName(), (HashMap<Long, String>) brokerData                                .getBrokerAddrs().clone());                            brokerDataList.add(brokerDataClone);                            foundBrokerData = true;                            for (final String brokerAddr : brokerDataClone.getBrokerAddrs().values()) {                                List<String> filterServerList = this.filterServerTable.get(brokerAddr);                                filterServerMap.put(brokerAddr, filterServerList);                            }                        }                    }                }            } finally {                this.lock.readLock().unlock();            }        } catch (Exception e) {            log.error("pickupTopicRouteData Exception", e);        }        if (log.isDebugEnabled()) {            log.debug("pickupTopicRouteData {} {}", topic, topicRouteData);        }        if (foundBrokerData && foundQueueData) {            return topicRouteData;        }        return null;    }
9.扫描不活跃的broker,该方法用于NameserverController中启用定时器清除不活跃的broker
    public void scanNotActiveBroker() {        Iterator<Entry<String, BrokerLiveInfo>> it = this.brokerLiveTable.entrySet().iterator();        while (it.hasNext()) {            Entry<String, BrokerLiveInfo> next = it.next();            long last = next.getValue().getLastUpdateTimestamp();            if ((last + BROKER_CHANNEL_EXPIRED_TIME) < System.currentTimeMillis()) {                RemotingUtil.closeChannel(next.getValue().getChannel());                it.remove();                log.warn("The broker channel expired, {} {}ms", next.getKey(), BROKER_CHANNEL_EXPIRED_TIME);                this.onChannelDestroy(next.getKey(), next.getValue().getChannel());            }        }    }
10.broker断链时候的处理,该方法主要由BrokerHousekeepingService调用,用于在broker与namesrv的链接断开时进行broker相关信息清除工作, 读锁升级到写锁
    public void onChannelDestroy(String remoteAddr, Channel channel) {        String brokerAddrFound = null;        if (channel != null) {            try {                try {                    this.lock.readLock().lockInterruptibly();                    Iterator<Entry<String, BrokerLiveInfo>> itBrokerLiveTable =                        this.brokerLiveTable.entrySet().iterator();                    while (itBrokerLiveTable.hasNext()) {                        Entry<String, BrokerLiveInfo> entry = itBrokerLiveTable.next();                        if (entry.getValue().getChannel() == channel) {                            brokerAddrFound = entry.getKey();                            break;                        }                    }                } finally {                    this.lock.readLock().unlock();                }            } catch (Exception e) {                log.error("onChannelDestroy Exception", e);            }        }        if (null == brokerAddrFound) {            brokerAddrFound = remoteAddr;        } else {            log.info("the broker's channel destroyed, {}, clean it's data structure at once", brokerAddrFound);        }        if (brokerAddrFound != null && brokerAddrFound.length() > 0) {            try {                try {                    this.lock.writeLock().lockInterruptibly();                    this.brokerLiveTable.remove(brokerAddrFound);                    this.filterServerTable.remove(brokerAddrFound);                    String brokerNameFound = null;                    boolean removeBrokerName = false;                    Iterator<Entry<String, BrokerData>> itBrokerAddrTable =                        this.brokerAddrTable.entrySet().iterator();                    while (itBrokerAddrTable.hasNext() && (null == brokerNameFound)) {                        BrokerData brokerData = itBrokerAddrTable.next().getValue();                        Iterator<Entry<Long, String>> it = brokerData.getBrokerAddrs().entrySet().iterator();                        while (it.hasNext()) {                            Entry<Long, String> entry = it.next();                            Long brokerId = entry.getKey();                            String brokerAddr = entry.getValue();                            if (brokerAddr.equals(brokerAddrFound)) {                                brokerNameFound = brokerData.getBrokerName();                                it.remove();                                log.info("remove brokerAddr[{}, {}] from brokerAddrTable, because channel destroyed",                                    brokerId, brokerAddr);                                break;                            }                        }                        if (brokerData.getBrokerAddrs().isEmpty()) {                            removeBrokerName = true;                            itBrokerAddrTable.remove();                            log.info("remove brokerName[{}] from brokerAddrTable, because channel destroyed",                                brokerData.getBrokerName());                        }                    }                    if (brokerNameFound != null && removeBrokerName) {                        Iterator<Entry<String, Set<String>>> it = this.clusterAddrTable.entrySet().iterator();                        while (it.hasNext()) {                            Entry<String, Set<String>> entry = it.next();                            String clusterName = entry.getKey();                            Set<String> brokerNames = entry.getValue();                            boolean removed = brokerNames.remove(brokerNameFound);                            if (removed) {                                log.info("remove brokerName[{}], clusterName[{}] from clusterAddrTable, because channel destroyed",                                    brokerNameFound, clusterName);                                if (brokerNames.isEmpty()) {                                    log.info("remove the clusterName[{}] from clusterAddrTable, because channel destroyed and no broker in this cluster",                                        clusterName);                                    it.remove();                                }                                break;                            }                        }                    }                    if (removeBrokerName) {                        Iterator<Entry<String, List<QueueData>>> itTopicQueueTable =                            this.topicQueueTable.entrySet().iterator();                        while (itTopicQueueTable.hasNext()) {                            Entry<String, List<QueueData>> entry = itTopicQueueTable.next();                            String topic = entry.getKey();                            List<QueueData> queueDataList = entry.getValue();                            Iterator<QueueData> itQueueData = queueDataList.iterator();                            while (itQueueData.hasNext()) {                                QueueData queueData = itQueueData.next();                                if (queueData.getBrokerName().equals(brokerNameFound)) {                                    itQueueData.remove();                                    log.info("remove topic[{} {}], from topicQueueTable, because channel destroyed",                                        topic, queueData);                                }                            }                            if (queueDataList.isEmpty()) {                                itTopicQueueTable.remove();                                log.info("remove topic[{}] all queue, from topicQueueTable, because channel destroyed",                                    topic);                            }                        }                    }                } finally {                    this.lock.writeLock().unlock();                }            } catch (Exception e) {                log.error("onChannelDestroy Exception", e);            }        }    }
11.打印所有信息,需要读锁
    public void printAllPeriodically() {        try {            try {                this.lock.readLock().lockInterruptibly();                log.info("--------------------------------------------------------");                {                    log.info("topicQueueTable SIZE: {}", this.topicQueueTable.size());                    Iterator<Entry<String, List<QueueData>>> it = this.topicQueueTable.entrySet().iterator();                    while (it.hasNext()) {                        Entry<String, List<QueueData>> next = it.next();                        log.info("topicQueueTable Topic: {} {}", next.getKey(), next.getValue());                    }                }                {                    log.info("brokerAddrTable SIZE: {}", this.brokerAddrTable.size());                    Iterator<Entry<String, BrokerData>> it = this.brokerAddrTable.entrySet().iterator();                    while (it.hasNext()) {                        Entry<String, BrokerData> next = it.next();                        log.info("brokerAddrTable brokerName: {} {}", next.getKey(), next.getValue());                    }                }                {                    log.info("brokerLiveTable SIZE: {}", this.brokerLiveTable.size());                    Iterator<Entry<String, BrokerLiveInfo>> it = this.brokerLiveTable.entrySet().iterator();                    while (it.hasNext()) {                        Entry<String, BrokerLiveInfo> next = it.next();                        log.info("brokerLiveTable brokerAddr: {} {}", next.getKey(), next.getValue());                    }                }                {                    log.info("clusterAddrTable SIZE: {}", this.clusterAddrTable.size());                    Iterator<Entry<String, Set<String>>> it = this.clusterAddrTable.entrySet().iterator();                    while (it.hasNext()) {                        Entry<String, Set<String>> next = it.next();                        log.info("clusterAddrTable clusterName: {} {}", next.getKey(), next.getValue());                    }                }            } finally {                this.lock.readLock().unlock();            }        } catch (Exception e) {            log.error("printAllPeriodically Exception", e);        }    }
12.获取系统所有的topic组装成TopicList
    public byte[] getSystemTopicList() {        TopicList topicList = new TopicList();        try {            try {                this.lock.readLock().lockInterruptibly();                for (Map.Entry<String, Set<String>> entry : clusterAddrTable.entrySet()) {                    topicList.getTopicList().add(entry.getKey());                    topicList.getTopicList().addAll(entry.getValue());                }                if (brokerAddrTable != null && !brokerAddrTable.isEmpty()) {                    Iterator<String> it = brokerAddrTable.keySet().iterator();                    while (it.hasNext()) {                        BrokerData bd = brokerAddrTable.get(it.next());                        HashMap<Long, String> brokerAddrs = bd.getBrokerAddrs();                        if (brokerAddrs != null && !brokerAddrs.isEmpty()) {                            Iterator<Long> it2 = brokerAddrs.keySet().iterator();                            topicList.setBrokerAddr(brokerAddrs.get(it2.next()));                            break;                        }                    }                }            } finally {                this.lock.readLock().unlock();            }        } catch (Exception e) {            log.error("getAllTopicList Exception", e);        }        return topicList.encode();    }
13.根据cluster获取topicList
    public byte[] getTopicsByCluster(String cluster) {        TopicList topicList = new TopicList();        try {            try {                this.lock.readLock().lockInterruptibly();                Set<String> brokerNameSet = this.clusterAddrTable.get(cluster);                for (String brokerName : brokerNameSet) {                    Iterator<Entry<String, List<QueueData>>> topicTableIt =                        this.topicQueueTable.entrySet().iterator();                    while (topicTableIt.hasNext()) {                        Entry<String, List<QueueData>> topicEntry = topicTableIt.next();                        String topic = topicEntry.getKey();                        List<QueueData> queueDatas = topicEntry.getValue();                        for (QueueData queueData : queueDatas) {                            if (brokerName.equals(queueData.getBrokerName())) {                                topicList.getTopicList().add(topic);                                break;                            }                        }                    }                }            } finally {                this.lock.readLock().unlock();            }        } catch (Exception e) {            log.error("getAllTopicList Exception", e);        }        return topicList.encode();    }
原创粉丝点击