RocketMQ组成
rocketmq服务端由两部分组成NameServer和Broker,NameServer类似于服务注册中心,Broker会把自己的地址注册到NameServer,生产者和消费者启动的时候会先从NameServer获取Broker的地址,再去从Broker发送和接受消息
Brocker主要启动流程
上图是rocketmq broker启动是做的事情,核心的类是BrokerController,主要是初始化了一些类,这些类的作用是
- DefaultMessageStore 用来做消息存储的,负责把消息持久化到磁盘,从磁盘中读取消息
- NettyRemotingServer 使用netty做服务器,负责网络通讯
- BrokerFixedThreadPoolExecutor rocketmq中有许多线程执行器,包括sendMessageExecutor(发送消息),pullMessageExecutor(拉取消息),queryMessageExecutor(查询消息),adminBrokerExecutor(默认处理)。这些线程执行器会通过registerProcessor注册到NettyRemotingServer ,每一个RequestCode会有一个对应的执行器,这样当请求到达nettyserver是,会根据RequestCode把请求分发到不同的执行器去处理请求
可以看到最终线程执行器会以RequestCode为键放到一个HashMap中
- broker会通过一个线程执行器去周期性的执行一些方法包括
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl(
"BrokerControllerScheduledThread")); //创建的线程执行器
BrokerController.this.getBrokerStats().record(); //每天执行一次,统计昨天put的message和get的message
BrokerController.this.consumerOffsetManager.persist(); // 默认5s执行一次,会把消费这的偏移量存到文件中 ${user.home}/store/config/consumerOffset.json.json
BrokerController.this.consumerFilterManager.persist(); // 没10s执行一次,会把消费者的消息过滤的信息持久化到文件 ${user.home}/store/config/consumerFilter.json
BrokerController.this.protectBroker(); // 当消费者消费太慢,会禁用到消费者组
BrokerController.this.printWaterMark(); //打新当前的Send Queue Size,Pull Queue Size,Query Queue Size,Transaction Queue Size
BrokerController.this.getMessageStore().dispatchBehindBytes() //没隔一分钟打印一次,dispath的消息偏移量和总的消息偏移量的差值
BrokerController.this.brokerOuterAPI.fetchNameServerAddr();// 如果nameserverAddr没有配的话,会通过http请求获取nameserver的地址
BrokerController.this.slaveSynchronize.syncAll();//如果节点是SLAVE会每隔一分钟从master同步一次数据
BrokerController.this.printMasterAndSlaveDiff();//打印master和slave相差的消息偏移量
nameserver http请求的url拼接规则,通过这种方式,可以动态添加和去除nameserver,不用固定写死到配置文件
public static String getWSAddr() {
String wsDomainName = System.getProperty("rocketmq.namesrv.domain", DEFAULT_NAMESRV_ADDR_LOOKUP);
String wsDomainSubgroup = System.getProperty("rocketmq.namesrv.domain.subgroup", "nsaddr");
String wsAddr = "http://" + wsDomainName + ":8080/rocketmq/" + wsDomainSubgroup;
if (wsDomainName.indexOf(":") > 0) {
wsAddr = "http://" + wsDomainName + "/rocketmq/" + wsDomainSubgroup;
}
return wsAddr;
}