源碼版本
- rocketmq:release-5.0.0
生産者一般使用
DefaultMQProducer producer = new DefaultMQProducer(PRODUCER_GROUP);
producer.setNamesrvAddr(DEFAULT_NAMESRVADDR);
producer.start();
如何設定NameServer位址
以下方式由高到底
- 通過java啟動參數設定,比如通過設定環境變量
System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, "127.0.0.1:9876");
- 通過設定伺服器環境變量(Linux)
-n 127.0.0.1:9876
- 通過代碼設定,比如
producer.setNamesrvAddr(DEFAULT_NAMESRVADDR);
- 通過HTTP服務來設定,當上面都沒有設定,會向一個HTTP位址發送請求來擷取NameServer位址,預設的URL是http://jmenv.tbsite.net:8080/rocketmq/nsaddr (淘寶的測試位址), 我們可以通過設定系統參數rocketmq.namesrv.domain來覆寫 jmenv.tbsite.net的值, 通過設定rocketmq.namesrv.domain.subgroup參數來覆寫nsaddr的值
可以看到4通過設定HTTP服務擷取NameServer的位址是最麻煩的,相當于自己還要出一個擷取擷取NameServer的接口,但是他是唯一支援動态增加NameServer,不用重新開機其他元件的方式
源碼分析
我們現在通過源碼方式分析上面的幾種設定方式
這裡的ClientConfig實際就是DefaultMQProducer,也就是我們發送消息的第一步,建立一個DefaultMQProducer
System.setProperty(MixAll.NAMESRV_ADDR_PROPERTY, "10.10.10.1:9999");
DefaultMQProducer producer = new DefaultMQProducer(PRODUCER_GROUP);
通過DefaultMQProducer的構造方法我們可以看到namesrvAddr的預設值是通過NameServerAddressUtils.getNameServerAddresses()
注意這裡的DefaultMQProducer是繼承了DefaultMQProducer
我們看看NameServerAddressUtils.getNameServerAddresses()方法的具體實作
可以看到首先通過擷取環境變量,其次是擷取系統環境變量
這裡就解釋了我們的1、2優先級。 看到了1、2的方法也很容易證明3的設定方式了,預設值是1、2,如果我們設定了就是3的設定方式 可以看到這裡的的namesrvAddr位址的擷取主要是通過clientConfig擷取的,而clientConfig的構造就是通過DefaultMQProducer構造的(前面分析的),而我們就可以通過在啟動Product的時候設定 比如
DefaultMQProducer producer = new DefaultMQProducer(PRODUCER_GROUP);
producer.setNamesrvAddr("name-server1-ip:9876;name-server2-ip:9876");
可以看到clientConfig就是在這裡通過clientConfig構造的
但是這裡的clientConfig就是DefaultMQProducer,我們可以通過debug的方式去确認
這裡可以看到就驗證了我們說的通過代碼設定。
我們繼續向下看 發現在product啟動這裡會去通過clientConfig擷取namesrvAddr,如果我們之前的代碼裡面沒有設定namesrvAddr的位址,那這裡就會為空,然後就通過fetchNameServerAddr去擷取namesrvAddr的位址
進到方法fetchNameServerAddr裡面我們會發現是通過TopAddressing類的fetchNSAddr方法
我們看看
這裡核心就是這個方法
return fetchNSAddr(true, 3000);
我們進去看看
可以看到這裡通過http去擷取namesrvAddr位址,url的擷取是通過this.wsAddr;擷取的,是以我們重點看看wsAddr如何初始化的
可以看到是通過MixAll.getWSAddr()的方法擷取的,我們看看getWSAddr方法
阿裡雲ons clinetbus直接設定的是NAMESRV_ADDR嗎
從上面我們可以确認最好的方式是通過http方式擷取namesrvAddr位址,那麼為什麼我們使用阿裡雲的ons-clinet是這種方式呢
Properties properties = new Properties();
properties.put(PropertyKeyConst.AccessKey, aliMQAccessKey);
properties.put(PropertyKeyConst.SecretKey, aliMQSecretKey);
properties.put(PropertyKeyConst.NAMESRV_ADDR, domainEventNameSrv);
return ONSFactory.createProducer(properties);
咋看好像是直接設定了NAMESRV_ADDR位址,其實我們随便看看源碼發現他也是設定的是wsAddr位址
總結
這裡我們通過源碼的方式驗證了rocketmq product擷取namesrvAddr的幾種方式,其中最推薦的還是通過HTTP服務來擷取,因為可以自由擴容