標籤:
ActiveMQ是一款功能強大的Message Service器,它支援許多種開發語言,例如Java, C, C++, C#等等。企業級Message Service器無論對伺服器穩定性還是速度,要求都很高,而ActiveMQ的分布式叢集則能很好的滿足這一需求,下面說說ActiveMQ的幾種叢集配置。
Queue consumer clusters
此叢集讓多個消費者同時消費一個隊列,若某個消費者出問題無法消費資訊,則未消費掉的訊息將被發給其他正常的消費者,結構圖如下:
Broker clusters
此種配置是一個消費者串連到多個broker叢集的中的一個broker,當該broker出問題時,消費者自動連接到其他一個正常的broker。消費者使用 failover:// 協議來串連broker。
failover:(tcp://localhost:61616,tcp://localhost:61617)
failover官網介紹 http://activemq.apache.org/failover-transport-reference.html
broker之間的通過靜態發現(static discovery)和動態發現(dynamic discovery)來維持彼此發現,下面來介紹靜態發現和動態發現的機制:
靜態發現:
靜態發現通過配置固定的broker uri來發現彼此,配置文法如下:
static:(uri1,uri2,uri3,...)?options
例如:
static:(tcp://localhost:61616,tcp://remotehost:61617?trace=false,vm://localbroker)?initialReconnectDelay=100
更多靜態發現介紹,見ActiveMQ官網 http://activemq.apache.org/static-transport-reference.html
動態發現:
動態發現機制是在各個broker啟動時通過Fanout transport來發現彼此,配置舉例如下:
<broker name="foo"> <transportConnectors> <transportConnector uri="tcp://localhost:0" discoveryUri="multicast://default"/> </transportConnectors> ... </broker>
更多動態發現機制介紹,見官網 http://activemq.apache.org/discovery-transport-reference.html
Networks of brokers
多個broker組成叢集,當其中一個broker的消費者出問題導致訊息堆積無法消費掉時,通過ActiveMQ支援的Network of Broker方案可將該broker堆積的訊息轉寄到其他有消費者的broker。
該方案主要有以下兩種配置方式:
1、為broker設定檔配置networkConnector元素
2、使用發現機制互相探測broker
Here is an example of using the fixed list of URIs:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://activemq.org/config/1.0"> <broker brokerName="receiver" persistent="false" useJmx="false"> <networkConnectors> <!-- Static discovery --> <networkConnector uri="static:(tcp://localhost:62001)"/> <!-- MasterSlave Discovery --> <!--<networkConnector uri="masterslave:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/> --> </networkConnectors> <persistenceAdapter> <memoryPersistenceAdapter/> </persistenceAdapter> <transportConnectors> <transportConnector uri="tcp://localhost:62002"/> </transportConnectors> </broker> </beans>
This example uses multicast discovery:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://activemq.org/config/1.0"> <broker name="sender" persistent="false" useJmx="false"> <networkConnectors> <networkConnector uri="multicast://default"/> </networkConnectors> <persistenceAdapter> <memoryPersistenceAdapter/> </persistenceAdapter> <transportConnectors> <transportConnector uri="tcp://localhost:0" discoveryUri="multicast://default"/> </transportConnectors> </broker> </beans>
Master Slave
通過部署多個broker執行個體,一個master和多個slave關係的broker來達到高可用性,有三種方案:
1、Master-Slave
2、SharedFile System Master Slave
3、JDBCMaster Slave
第一種方案由於只可以由兩個AMQ執行個體組件,實際應用情境並不廣泛;
第三種方案支援N個AMQ執行個體組網,但他的效能會受限於資料庫;
第二種方案同樣支援N個AMQ執行個體組網,基於kahadb儲存策略,亦可以部署在Distributed File System上,應用靈活、高效且安全。
Master Slave方案當其中一個broker啟動並拿到獨佔鎖時自動成為master,其他後續的broker則一直等待鎖,當master宕機釋放鎖時其他slave拿到獨佔鎖則自動成為master,部署結構如下:
第二種方案的配置只需修改config檔案夾下activemq.xml檔案,修改訊息持久化使用的方案:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="D:/Platform/mq_share_file"> ... <persistenceAdapter> <kahaDB directory="D:/Platform/mq_share_file/kahadb" enableIndexWriteAsync="true" enableJournalDiskSyncs="false"/> </persistenceAdapter> ...</broker>
訊息生產者代碼:
public class P2PSender { private static final String QUEUE = "client1-to-client2"; public static void main(String[] args) { // ConnectionFactory :串連工廠,JMS用它建立串連 ConnectionFactory connectionFactory; // Connection :JMS用戶端到JMS Provider的串連 Connection connection = null; // Session:一個發送或接收訊息的線程 Session session; // Destination :訊息的目的地;訊息發送給誰. Destination destination; // MessageProducer:訊息寄件者 MessageProducer producer; // TextMessage message; // 構造ConnectionFactory執行個體對象,此處採用ActiveMq的實現 connectionFactory = new ActiveMQConnectionFactory( "failover:(tcp://localhost:61616?wireFormat.maxInactivityDuration=0,tcp://localhost:61617?wireFormat.maxInactivityDuration=0)"); try { // 構造從工廠得到連線物件 connection = connectionFactory.createConnection(); // 啟動 connection.start(); // 擷取操作串連 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); destination = session.createQueue(QUEUE); // 擷取session,FirstQueue是一個伺服器的queue destination = session.createQueue("FirstQueue"); // 得到訊息產生者【寄件者】 producer = session.createProducer(destination); // 設定不持久化 producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); // 構造訊息 sendMessage(session, producer); // session.commit(); connection.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (null != connection) { try { connection.close(); } catch (JMSException e) { e.printStackTrace(); } } } } public static void sendMessage(Session session, MessageProducer producer) throws Exception { for (int i = 1; i <= 1; i++) { Date d = new Date(); TextMessage message = session.createTextMessage("ActiveMQ發送訊息" + i + " " + new Date()); System.out.println("發送訊息:ActiveMQ發送的訊息" + i + " " + new Date()); producer.send(message); } }}
訊息消費者代碼:
public class P2PReceiver { private static final String QUEUE = "client1-to-client2"; public static void main(String[] args) { // ConnectionFactory :串連工廠,JMS用它建立串連 ConnectionFactory connectionFactory; // Connection :JMS用戶端到JMS Provider的串連 Connection connection = null; // Session:一個發送或接收訊息的線程 Session session; // Destination :訊息的目的地;訊息發送給誰. Destination destination; // 消費者,訊息接收者 MessageConsumer consumer; connectionFactory = new ActiveMQConnectionFactory("failover:(tcp://localhost:61616?wireFormat.maxInactivityDuration=0,tcp://localhost:61617?wireFormat.maxInactivityDuration=0)"); try { // 得到連線物件 connection = connectionFactory.createConnection(); // 啟動 connection.start(); // 擷取操作串連 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 建立Queue destination = session.createQueue(QUEUE); consumer = session.createConsumer(destination); while (true) { TextMessage message = (TextMessage) consumer.receive(); if (null != message) { System.out.println("收到訊息" + message.getText()); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != connection) connection.close(); } catch (Throwable ignore) { } } }}
轉自 ActiveMQ的幾種叢集配置
[轉]ActiveMQ的幾種叢集配置