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;
}