RocketMQ NameServer 核心源碼解析
帶著問題 往下看 (namesrv)
- 我們在寫組件的時候 怎么管理version
- 如果現(xiàn)在讓你 維護一個 各個jar包公用的屬性
- System.exit(-1); 0 -1 -2 各種數(shù)都是干什么的,什么時候 用哪個
- 環(huán)境變量如果不想使用 ROCKETMQ_HOME, 想變?yōu)?xxx 這怎么做,能做么?
- 我們啟動broker 老是用 -n ip:9876 9876是什么,我們可以改變么?怎么改
- 大家如果想 把命令啟動帶著的 -c -p等參數(shù)放到 我們的屬性中,怎么寫代碼?
- 如果我們想 自己設(shè)置使用的log 組件,怎么辦
- 遍歷 Field[] 的時候 想跳過 static的屬性 怎么寫代碼?
- 多個對象的 屬性需要進行聚合到一個對象中,要是你 怎么寫
- KVConfigManager 有什么作用,怎么保證的 并發(fā)操作的數(shù)據(jù)正確性?你感覺有什么問題么?
- KVConfigManager 怎么保證的 持久化?
- 怎么在 并發(fā)操作的時候 保證數(shù)據(jù)的安全性?
- 方法的參數(shù) 使用final 有什么用?
- 怎么判斷的broker 是不是master
- netty 怎么讓nameserver 通知broker 信息的。
- nameserver 是否存活的判斷標準是什么? 能修改么? 怎么修改
- Runtime.getRuntime().addShutdownHook 有什么用,沒有不行么?
- @ImportantField 干什么的? 什么時候 使用
- 在同一臺計算機上部署多個代理時 想?yún)^(qū)分日志路徑 用哪個參數(shù),調(diào)成什么?
- broker 為什么 -p 和 -m 同時有的時候 -m的總是不生效呢?
請思考下 寫寫你的答案 再往下看
nameserver 啟動的邏輯
nameserver 功能
- 管理broker 集群
- 屬于注冊中心 業(yè)務(wù)端 和nameserver 進行連接,獲取broker地址
- 負責維護broker 連接/心跳/監(jiān)控
nameserver 問題解答
我們在寫組件的時候 怎么管理version
一方面是 在父類的 pom.xml 通過 進行 控制版本,然后 業(yè)務(wù)端通過
<dependencyManagement> <dependencies> <dependency> <groupId>com.xxx</groupId> <artifactId>xxx</artifactId> <version>4.0.0-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
這是第一個 ,第二個 是 rocketmq 這種 在common 包下面 新建一個 MQVersion 管理版本
這里會有一個問題,那這個版本管理 我用在哪里啊,不用不行么?
- 為了方便測試,測試的時候 可能因為版本有差異 導致的問題。指定version 就沒有這個問題了 2 broker 操作也是,(其實一句話 為了之后的版本兼容)比如
if (version < MQVersion.Version.V3_0_7_SNAPSHOT.ordinal()) { result.setCode(ResponseCode.SYSTEM_ERROR); result.setRemark("the client does not support this feature. version=" + MQVersion.getVersionDesc(version)); log.warn("[get-consumer-status] the client does not support this feature. channel={}, version={}", RemotingHelper.parseChannelRemoteAddr(entry.getKey()), MQVersion.getVersionDesc(version)); return result; } else if (UtilAll.isBlank(originClientId) || originClientId.equals(clientId)) { }
如果現(xiàn)在讓你 維護一個 各個jar包公用的屬性
1 在common包搞一個 公共的實體類 隨時用隨時取唄,大不了就一個map 然后就put get
2 System.setProperty 底層就是全局 map 進行put get
extends Hashtable<Object,Object>
環(huán)境變量如果不想使用 ROCKETMQ_HOME, 想變?yōu)?xxx 這怎么做,能做么?
設(shè)置 rocketmq.home.dir=xxx
我們啟動broker 老是用 -n ip:9876 9876是什么,我們可以改變么?怎么改
nettyServerConfig.setListenPort(9876);
代碼指定 的netty 監(jiān)聽端口,一般情況不改
大家如果想 把命令啟動帶著的 -c -p等參數(shù)放到 我們的屬性中,怎么寫代碼?
MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), namesrvConfig);
這是先把commandLine 轉(zhuǎn)變?yōu)?Properties 對象,然后調(diào)用 namesrvConfig 反射方法 賦值
如果我們想 自己設(shè)置使用的log 組件,怎么辦
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); configurator.doConfigure(namesrvConfig.getRocketmqHome() + "/conf/logback_namesrv.xml");
遍歷 Field[]
遍歷 Field[]的時候 想跳過 static的屬性 怎么寫代碼?
(field.getModifiers() & 0x00000008) != 0 如果為true 就是 static false為 非static
多個對象的 屬性需要進行聚合到一個對象中,要是你 怎么寫
for (Entry<Object, Object> next : from.entrySet()) { Object fromObj = next.getValue(), toObj = to.get(next.getKey()); if (toObj != null && !toObj.equals(fromObj)) { log.info("Replace, key: {}, value: {} -> {}", next.getKey(), toObj, fromObj); } to.put(next.getKey(), fromObj); }
因為 可能同時操作這個對象 導致 數(shù)據(jù)不一致 ,所以要加上 讀寫鎖的 寫鎖
KVConfigManager 有什么作用
KVConfigManager 有什么作用,怎么保證的 并發(fā)操作的數(shù)據(jù)正確性?你感覺有什么問題么?
是 kv 配置的管理器,主要是
HashMap<String/* Namespace */, HashMap<String/* Key */, String/* Value */>> configTable
以后寫map 也要像這種方式 寫注釋。
//讀取的是 ./namesrv/kvConfig.json kvConfigPath = System.getProperty("user.home") + File.separator + "namesrv" + File.separator + "kvConfig.json";
行吧 ,現(xiàn)在還不知道 這些kv的作用,先看看怎么存儲的,到用的時候 我們接上,先知道 kv 存儲在KVConfigManager類 configTable 屬性中
putKVConfig 使用的 ReentrantReadWriteLock 的寫鎖 保證數(shù)據(jù)一致性,如果map的key 存在了,不會進行覆蓋,而是 跳過。
KVConfigManager 持久化
KVConfigManager 怎么保證的 持久化?
執(zhí)行過 上面的 那些方法,執(zhí)行 persist ,加讀鎖,如下圖
怎么在 并發(fā)操作的時候 保證數(shù)據(jù)的安全性?
一方面 是 不可變類,其中返回屬性的時候 要進行copy 簡單來說 就是我通過get 方法出去的 對象 是 copy的對象,而不是 原來的對象,防止 外面通過引用 修改 屬性值,把我們的對象 屬性 進行修改。
方法的參數(shù) 使用final 有什么用?
- 確保,不會也不能對于參數(shù)進行修改,保證了調(diào)用發(fā)起方數(shù)據(jù)的安全;
- 避免在方法體中修改參數(shù),引起不必要的錯誤
- 程序員工作不是一個人的工作,你設(shè)置為final,別人將來維護的時候一看就知道這個變量不能修改,而不需要去記憶這個是不能變化的值,是常量。這個是代碼規(guī)范。
broker 是不是master判斷
怎么判斷的broker 是不是master
//0 == brokerId MixAll.MASTER_ID == brokerId
這個其實可以 抽出來一個公共的方法, 方便之后的修改
netty 怎么讓nameserver 通知broker 信息的。
netty 保存的 channel 到時候用了 直接從map 獲取 然后發(fā)送消息
nameserver 是否存活的判斷標準是什么? 能修改么? 怎么修改
BROKER_CHANNEL_EXPIRED_TIME = 1000 * 60 * 2
static final 寫死的,如果 最后一次心跳時間 + 2分鐘 都小于System.currentTimeMillis() 執(zhí)行刪除操作
- 關(guān)閉 netty channel
- brokerLiveTable 刪除對應(yīng)的實例
這是一個定時任務(wù) 從項目 啟動5s之后 ,每10s執(zhí)行一次,說明 對broker的感知 會有些許 延遲。(最大也就 20s,一般10s以內(nèi)感知)
Runtime.getRuntime().addShutdownHook 有什么用,沒有不行么?
當程序正常退出,系統(tǒng)調(diào)用 System.exit方法或虛擬機被關(guān)閉時才會執(zhí)行添加的shutdownHook線程。其中shutdownHook是一個已初始化但并不有啟動的線程,當jvm關(guān)閉的時候,會執(zhí)行系統(tǒng)中已經(jīng)設(shè)置的所有通過方法addShutdownHook添加的鉤子,當系統(tǒng)執(zhí)行完這些鉤子后,jvm才會關(guān)閉。所以可通過這些鉤子在jvm關(guān)閉的時候進行內(nèi)存清理、資源回收等工作。
@ImportantField
@ImportantField 干什么的? 什么時候 使用
最后的true 代表 是否只打印關(guān)鍵屬性,寫@ImportantField的 就一定會打,沒有這個注解的就不打印了
MixAll.printObjectProperties(console, brokerConfig, true);
在同一臺計算機上部署多個代理時 想?yún)^(qū)分日志路徑 用哪個參數(shù),調(diào)成什么?
isolateLogEnable 改為 true
if (brokerConfig.isIsolateLogEnable()) { System.setProperty("brokerLogDir", brokerConfig.getBrokerName() + "_" + brokerConfig.getBrokerId()); } if (brokerConfig.isIsolateLogEnable() && messageStoreConfig.isEnableDLegerCommitLog()) { System.setProperty("brokerLogDir", brokerConfig.getBrokerName() + "_" + messageStoreConfig.getdLegerSelfId()); }
broker 為什么 -p 和 -m 同時有的時候 -m的總是不生效呢?
無論是 -p 還是 -m 都是print 輸出,本來就是希望打印日志,然后進程停止。
opt = new Option("p", "printConfigItem", false, "Print all config item"); opt = new Option("m", "printImportantConfig", false, "Print important config item");
總結(jié)
這些 只是 namestr 的NamesrvController 初始化,更多關(guān)于RocketMQ NameServer 解析的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談為什么Java中1000==1000為false而100==100為true
這篇文章主要介紹了淺談為什么Java中1000==1000為false而100==100為true,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09SpringCloud?微服務(wù)數(shù)據(jù)權(quán)限控制的實現(xiàn)
這篇文章主要介紹的是權(quán)限控制的數(shù)據(jù)權(quán)限層面,意思是控制可訪問數(shù)據(jù)資源的數(shù)量,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2021-11-11如何用注解的方式實現(xiàn)Mybatis插入數(shù)據(jù)時返回自增的主鍵Id
這篇文章主要介紹了如何用注解的方式實現(xiàn)Mybatis插入數(shù)據(jù)時返回自增的主鍵Id,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07Java網(wǎng)絡(luò)編程之URL+URLconnection使用方法示例
這篇文章主要介紹了Java網(wǎng)絡(luò)編程之URL+URLconnection使用方法示例,還是比較不錯的,這里分享給大家,供需要的朋友參考。2017-11-11Java Netty HTTP服務(wù)實現(xiàn)過程解析
這篇文章主要介紹了Java Netty HTTP服務(wù)實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-08-08使用Java注解和反射實現(xiàn)JSON字段自動重命名
這篇文章主要介紹了如何使用Java注解和反射實現(xiàn)JSON字段自動重命名,文中通過代碼示例和圖文介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下2024-08-08SpringBoot如何啟動自動加載自定義模塊yml文件(PropertySourceFactory)
這篇文章主要介紹了SpringBoot如何啟動自動加載自定義模塊yml文件(PropertySourceFactory),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07