RocketMQ学习-NameServer-2

上篇文章主要梳理了NameServer的启动器和配置信息,并复习了JVM中的关闭钩子这个知识点。这篇文章看下NameServer的其他模块。建议带着如下三个问题阅读:

NameServer管理哪些信息?如何管理的?

NameServer中对Netty的使用案例?

NameServer中对Java并发编程使用案例?

一、NamesrvController

作用:NameServer模块的控制器

主要属性

namesrvConfig:name server的配置信息

nettyServerConfig:name server中作为netty服务端的配置

scheduledExecutorService:调度线程池,用于:(1)周期性检查broker信息;(2)周期性打印路由信息;这两个检查每隔5秒交替进行。

kvConfigManager:name server配置的操作接口

routeInfoManager:name server路由信息的操作接口

remotingServer:netty服务器

brokerHousekeepingService:监听连接的broker的通道的关闭或异常事件,用于清理broker信息;

remotingExecutor:服务端处理请求的线程池

代码如下

主要方法

initialize:初始化

registerProcessor:注册处理器

其他还有:构造方法、start方法、shutdown方法

Java并发

Executors.newFixedThreadPool(),用于创建固定数量的线程池,根据线程池的运行原理:线程池启动时候没有线程,当新任务到来时就创建线程处理;由于coreSize和maxSize设置为相同大小,如果任务来的时候线程已经达到coreSize,就直接放入等待队列;keepAlive设置为0,目的是让线程数不会超过coreSize;blockqueue设置为LinkedBlockingQueue,表示是无界队列,最多可以放Integer.MAX_VALUE个任务。

周期线程池

NameServerController中使用了调度线程池,我们看下创建一个调度线程池的方法,即Executors.newSingleThreadScheduledExecutor(),该方法的定义如下所示:

这种线程池的创建又委托给了DelegatedScheduledExecutorService类,这里为什么这么设计,不是太理解。不过可以看下真正创建调度线程池的代码:

上面这个方法,关键在于两点:(1)maxSize选了Integer.MAX_VALUE;(2)任务队列使用了延迟队列;再回头去看那个委托类的代码,就可以明白,委托类包装了ScheduledExecutorService执行器,提供了延迟或周期执行的接口。

找到上面几个主要类和接口的类图,再综合上面的代码,可以这么理解:Executors是一个工具类,提供了生成不同的线程池的工厂方法,其中包括newSingleThreadScheduledExecutor方法,由于ScheduledExecutorService扩展了ExecutorService接口,同时又想重用AbstractExecutorService中的一些方法,因此需要一个委托类,将ExecutorService和ScheduledExecutorService的功能整合在一个类中。

Netty

RemotingServer是name server中的通信服务端,在name controller初始化name server模块的时候,会将name server的请求处理器注册到netty服务器上。

二、DefaultRequestProcessor

在NameServerController中会注册请求处理器,那么name server的请求处理器实现了哪些接口呢,请看代码:

从这个代码中可以看出两个方面的内容:

如何使用Netty处理网络请求。关键数据结构:(1)RemotingCommand:自定义的协议,携带请求参数和响应(2)ChannelHandlerContext:netty的数据结构,携带channel相关的信息。设计模型:processRequest:通过请求码进行请求转发;

请求处理方法(跟协议相关,具体参见remote模块)(1)processRequest:请求分发;(2)putKVConfig:将配置信息放在内存中;(3)getKVConfig:返回配置信息(4)deleteKVConfig:删除配置信息;(5)注册broker,支持两个注册方式:带过滤服务的(MQ版本在V311之后的)、不带过滤服务的,等其他处理方法。

三、BrokerHousekeepingService

该模块实现了ChannelEventListener接口,每个broker都会跟name server建立一个连接通道,当这个通道发生异常事件时,需要及时在name server这边清理掉对应的broker信息。异常事件的类型有:(1)通道关闭时;(2)通道抛出异常时;(3)通道空闲时。

四、RouteInfoManager

这个模块是name server的核心模块,真正管理broker、消息队列等相关信息的地方。代码如下:

主要属性的含义如下:

BROKERCHANNELEXPIRED_TIME,表示一个broker距离上次发心跳包的最长时间,即120秒;

使用可重入读写锁实现并发安全、使用轻量级的非线程安全容器实现高效并发;【这点非常重要】

topicQueueTable:用于管理topic和属于这个topic的队列的映射关系;

brokerAddrTable:用于管理某个broker和它对应的信息

clusterAddrTable:用于管理broker集群和集群中对应的broker的映射关系

brokerLiveTable:用于管理broker的存活信息

filterServerTable:用于管理broker和过滤服务列表【暂不理解】

关于ReentrantReadWriteLock:

这里使用的锁是非公平锁

ReentrantReadWriteLock基于Sync、ReadLock、WriteLock三个模块实现,Sync负责处理公平与否的问题。ReadLock和WriteLock通过锁外部对象ReentrantReadWriteLock来处理并发。在RoutInfoManager中的使用案例如下:

五、KVConfigManager

这个模块用于管理name server自己的配置信息,配置信息以json信息存放在文件中,以二维数组形式存在于内存中,请看代码:

这个类对外暴露的方法有:

load方法:将配置信息加载到内存中

putKVConfig方法:将配置信息持久化

deleteKVConfig方法:删除指定的配置项

getKVListByNamespace和getKVConfig用于查询配置信息

参考资料

消息队列技术点梳理

netty的线程模型

《Java并发编程的艺术》

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180403G1Q6ZY00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券