ActiveMQ是apache的一個(gè)開(kāi)源JMS服務(wù)器,不僅具備標(biāo)準(zhǔn)JMS的功能,還有很多額外的功能。公司里引入ActiveMQ后,ActiveMQ成里我們公司業(yè)務(wù)系統(tǒng)中最重要的一個(gè)環(huán)節(jié)。所有應(yīng)用都通過(guò)jms集成,如果ActiveMQ出了故障,整個(gè)系統(tǒng)就癱瘓了。因此,頭對(duì)ActiveMQ的性能,可靠性,以及如何正確使用,是非常的關(guān)心的,而我就被指派來(lái)做關(guān)于ActiveMQ的調(diào)研,本文對(duì)此做了些總結(jié)。
1 使用jms需要注意的問(wèn)題
一下所述的問(wèn)題,不僅是對(duì)ActiveMQ,對(duì)于其他的JMS也一樣有效。
1.1 不要頻繁的建立和關(guān)閉連接
JMS使用長(zhǎng)連接方式,一個(gè)程序,只要和JMS服務(wù)器保持一個(gè)連接就可以了,不要頻繁的建立和關(guān)閉連接。頻繁的建立和關(guān)閉連接,對(duì)程序的性能影響還是很大的。這一點(diǎn)和jdbc還是不太一樣的。
1.2 Connection的start()和stop()方法代價(jià)很高
JMS的Connection的start()和stop()方法代價(jià)很高,不能經(jīng)常調(diào)用。我們?cè)囉玫臅r(shí)候,寫(xiě)了個(gè)jms的connection pool,每次將connection取出pool時(shí)調(diào)用start()方法,歸還時(shí)調(diào)用stop()方法,然而后來(lái)用jprofiler發(fā)現(xiàn),一般的cpu時(shí)間都耗在了這兩個(gè)方法上。
1.3 start()后才能收消息
Connection的start()方法調(diào)用后,才能收到j(luò)ms消息。如果不調(diào)用這個(gè)方法,能發(fā)出消息,但是一直收不到消息。不知道其它的jms服務(wù)器也是這樣。
1.4 顯示關(guān)閉Session
如果忘記了最后關(guān)閉Connection或Session對(duì)象,都會(huì)導(dǎo)致內(nèi)存泄漏。這個(gè)在我測(cè)試的時(shí)候也發(fā)現(xiàn)了。本來(lái)以為關(guān)閉了Connection,由這個(gè)Connection生成的Session也會(huì)被自動(dòng)關(guān)閉,結(jié)果并非如此,Session并沒(méi)有關(guān)閉,導(dǎo)致內(nèi)存泄漏。所以一定要顯示的關(guān)閉Connection和Session。
1.5 對(duì)Session做對(duì)象池
對(duì)Session做對(duì)象池,而不是Connection。Session也是昂貴的對(duì)象,每次使用都新建和關(guān)閉,代價(jià)也非常高。而且后來(lái)我們發(fā)現(xiàn),原來(lái)Connection是線程安全的,而Session不是,所以后來(lái)改成了對(duì)Session做對(duì)象池,而只保留一個(gè)Connection。
2 集群
ActiveMQ有強(qiáng)大而靈活的集群功能,但是使用起來(lái)還是會(huì)有很多陷阱。
2.1 broker cluster和 master-slave
ActiveMQ可以做broker的集群,也可以做master-slave方式的集群。前者能在多個(gè)broker之前fail-over和load-balance,但是在某個(gè)節(jié)點(diǎn)出故障時(shí),可能導(dǎo)致消息丟失;而后者能實(shí)時(shí)備份消息,和fail-over,但是不能load-balance。broker cluser的方式,在一個(gè)broker上發(fā)送的消息可以在其它的broker上收到。當(dāng)一個(gè)broker失效時(shí),客戶端可以自動(dòng)的轉(zhuǎn)到別的broker上運(yùn)行,多個(gè)broker可以同時(shí)提供服務(wù),但是消息只存儲(chǔ)在一個(gè)broker上,如果那個(gè)broker失效了,那么客戶端直到它重新啟動(dòng)后才能收到該broker上的消息,假如很不幸,那個(gè)broker的存儲(chǔ)介質(zhì)壞了,那么消息就丟失掉了。
Master-slave方式中,只有master提供服務(wù),slave只是實(shí)時(shí)的備份master的數(shù)據(jù),所以消息不會(huì)丟失。當(dāng)master失效時(shí),slave會(huì)自動(dòng)升為master,客戶端會(huì)自動(dòng)轉(zhuǎn)到slave上工作,所以能fail-over。由于只有master提供服務(wù),所以不能將負(fù)載分到多個(gè)broker上。
其實(shí)單個(gè)broker的性能已經(jīng)是相當(dāng)?shù)捏@人了,在我們公司的機(jī)器上能達(dá)到每秒收發(fā)4000個(gè)消息,沒(méi)個(gè)消息4K字節(jié)這樣的速度,足夠公司目前的需要了,而公司并不希望丟失任何數(shù)據(jù),所以我們選擇使用master-slave模式。
2.2 多種master-slave模式
master-slave也有多種實(shí)現(xiàn)方式。它們的不同只是在共享數(shù)據(jù)和鎖機(jī)制上。
2.2.1 Pure master-slave
Pure master-slave,顯示的在配置文件中指定一個(gè)broker做為另一個(gè)broker的slave。運(yùn)行時(shí),slave同過(guò)網(wǎng)絡(luò)自動(dòng)從master出復(fù)制數(shù)據(jù),同時(shí)在和master失去連接時(shí)自動(dòng)升級(jí)為master。當(dāng)master失效,slave成為master后,如果要讓原先的master重新投入運(yùn)行,需要停掉運(yùn)行中的slave(現(xiàn)在升級(jí)為master了),手動(dòng)復(fù)制slave中的數(shù)據(jù)到master中。再重新啟動(dòng)master和slave。這種方式最簡(jiǎn)單,效率也不錯(cuò),但是只能有兩臺(tái)做集群,只能fail-over一次,而且需要停機(jī)回復(fù)master-slave結(jié)構(gòu)。
2.2.2 JDBC master-slave
這種方式不需要特殊的配置,只要讓所有的節(jié)點(diǎn)都把數(shù)據(jù)存儲(chǔ)到同一個(gè)數(shù)據(jù)庫(kù)中。先拿到數(shù)據(jù)庫(kù)表的鎖的節(jié)點(diǎn)成為master,一旦它失效了,其它的節(jié)點(diǎn)獲得鎖,就可以成為master。因?yàn)閿?shù)據(jù)通過(guò)數(shù)據(jù)庫(kù)共享,放在一個(gè)地方,不需要停機(jī)恢復(fù)master-slave。這種方式,需要額外的數(shù)據(jù)庫(kù)服務(wù)器,如果數(shù)據(jù)庫(kù)失效了,那么就全失效了,而且速度不是很快。我們?cè)谟胢ysql測(cè)試時(shí),并沒(méi)有成功,master失效后,其他的節(jié)點(diǎn)始終沒(méi)有升級(jí)成slave,可能是數(shù)據(jù)庫(kù)配置的問(wèn)題。
2.2.3 Share file master-slave
這種方式類似于前者,也不需要特別的配置,只是通過(guò)共享文件系統(tǒng)來(lái)共享數(shù)據(jù),靠文件鎖實(shí)現(xiàn)只有一臺(tái)成為master。共享文件系統(tǒng)的方式有很多,我們測(cè)試了nfs v4 (v3有bug,不行), 最終在穩(wěn)定性,效率等方面不是很滿意,可能是通過(guò)網(wǎng)絡(luò)太慢了。
測(cè)試過(guò)眾多master-slave模式后發(fā)現(xiàn),pure方式管理起來(lái)麻煩,jdbc方式成本高,效率低,share file方式需要高性能的共享文件,都有缺點(diǎn)。鑒于單臺(tái)activeMQ很可靠,而我們的基礎(chǔ)平臺(tái)組愿意用硬件備份,最終還是決定不用master-slave了,也不用broker cluster,就用單臺(tái),通過(guò)硬件冗余保證數(shù)據(jù)不會(huì)丟失,并找另外一臺(tái)刀片機(jī)做冷備,在主服務(wù)器失效時(shí)頂替。
相關(guān)文章: