路由管理
NameServer需要为生产者和消费者提供关于Topic的路由信息,还得管理集群中的所有Broker节点,包括时刻监控Broker的存活状态、接收Broker的注册信息,而这些路由的基础信息,在RouteInfoManager这个类中。
元信息
RouteInfoManager是路由信息的管理类
//NameServer与Broker空闲连接时长,在2minNameServer之内没有收到Broker的心跳包,则NameServer会关闭与该Broker的连接并删除Broker的路由信息。 private final static long BROKER_CHANNEL_EXPIRED_TIME = 1000 * 60 * 2; //读写锁,用来保护以下用于存储关键信息的非线程安全容器HashMap private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Topic消息队列路由信息,消息发送时根据路由表进行负载均衡 private final HashMap<String/* topic */, List<QueueData>> topicQueueTable; // Broker基础信息,包括broker所属集群的名称、broker的名称以及主备Broker地址。 private final HashMap<String/* brokerName */, BrokerData> brokerAddrTable; //Broker集群信息,存储集群中所有Broker的名称 private final HashMap<String/* clusterName */, Set<String/* brokerName */>> clusterAddrTable; //Broker状态信息,主要是接收broker心跳包更新时间戳,用于路由删除 private final HashMap<String/* brokerAddr */, BrokerLiveInfo> brokerLiveTable; //Broker上的FilterServer列表,用于类模式消息过滤 private final HashMap<String/* brokerAddr */, List<String>/* Filter Server */> filterServerTable;
brokerLiveTable就是存放Broker节点发送来的的心跳包更新时间戳,NameServer就是根据brokerLiveTable属性中BrokerLiveInfo对象的lastUpdateTimestamp时间戳属性来判断该Broker节点是否可用的
服务注册
Broker在NameServer上注册,NameServer需要接收Broker发送的心跳包然后更新相应的路由元信息即可
Broker 发送心跳包
org.apache.rocketmq.broker.BrokerStartup类的启动方法,在启动时会注册一个定时线程池
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister()); } catch (Throwable e) { log.error("registerBrokerAll Exception", e); } } }, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod(), 60000)), TimeUnit.MILLISECONDS);
BrokerConfig#registerNameServerPeriod属性默认值是30秒,决定Broker向NameServer注册的时间间隔,可以通过在启动Broker时用-c参数指定配置文件,在配置文件中修改registerNameServerPeriod属性的值
在默认情况下,Broker会在启动10秒后每隔30秒向NameServer发送心跳包,具体定时任务的业务在BrokerController#registerBrokerAll -> BrokerController#doRegisterBrokerAll -> BrokerOuterAPI#registerBrokerAll方法中
Broker在发送心跳包时,会遍历集群中所有的所有NameServer通过调用BrokerOuterAPI#registerBroker方法发送心跳包,并且这是一个oneway消息,也就是说只需要关注是否发送成功,无需等待返回结果。NameServer 接收心跳包
当Broker向NameServer发送心跳包之后,NameServer自然会进行接收,而在NameServer中接收网络请求的类叫做DefaultRequestProcessor,在这个类的processRequest方法中会对自定义的请求code进行switch-case的选择
case RequestCode.REGISTER_BROKER: 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); }
在RouteInfoManager#registerBroker方法中,其实是基于心跳包的数据对RouteInfoManager对象的五个属性进行维护——clusterAddrTable, brokerAddrTable, topicQueueTable, brokerLiveTable, filterServerTable
服务删除
NameServer会每隔10秒扫描一次RouteInfoManager#brokerLiveTable表,根据Broker对应的lastUpdateTimestamp时间戳是否超过120秒未更新来判断Broker是否需要删除。
一种就是:若Broker正常停机,Broker会发送一个标记为RequestCode.UNREGISTER_BROKER的消息,而在NameServer中会通过调用RouteInfoManager#unregisterBroker方法来进行服务的反注册,删除缓存在RouteInfoManager类中五个HashMap中对应的数据。
服务发现
服务发现就是指使用一个注册中心来记录分布式系统中的全部服务的信息,以便其他服务能够快速的找到这些已注册的服务。 在RocketMQ中就是当Topic信息发生变化以后(新增、修改或删除),NameSever会接收Broker发送的心跳包更新该Topic信息,但是NameSever并不主动将最新的路由信息推送给客户端,而是客户端定时拉取Topic的最新路由信息。
浙公网安备 33010602011771号