HornetQ JMS 集羣 之 (Static discovery)

序言:

  一款 好的中間件必然少不了高可用性和高吞吐量的特性了,當然這些特性在Hornetq裏面也得到非常好的實現。並且支持服務器端和client集羣方案,不錯吧 呵呵... 大多數的JBOSS 系列產品,都提供兩種主要技術來實現動態集羣(UDP 和 Jgroup). 在Hornetq 也提供另外一種靜態配置集羣連接器,在某些情況下UDP不能使用,使用靜態發現同樣可以實現集羣功能。本文主要闡述Hornetq cluster的方案之一. 也是侷限於作者本地環境, 因爲在本地主機上只有一塊物理網卡。 所以 我選擇用靜態發現。

      無論是動態還是動態的方式搭建集羣環境,都可以採用對稱以及非對稱的集羣拓撲。什麼是對稱 或者 非對稱 拓撲?

  1. 對稱: A < --> B <-->C <--->A , 這種拓撲結構下 所有的節點都能夠發現其他集羣節點。

  2. 非對稱: A --> B --> C 在這種拓撲結構下A節點是不能察覺到C節點也在集羣環境下。這裏節點A到節點C實際上是有兩跳, 在接下來的配置中可以制定集羣的最大跳數。

 

  前面一直提及一個概念就是靜態發現其他集羣節點的配置方式,什麼是靜態發現? 簡單而言就是顯示的告訴A節點B節點和C節點在集羣環境中。而不是通過廣播數據包去探測有哪些節點加入到了集羣節點中。當然這種方式屬於服務器端集,稍後我們可以看看客戶端集羣怎麼做得類似於這樣的靜態配置不過要簡單許多。 接下來一起看看怎麼類配置和測試。

 

環境準備:

1, 準備個hornetq sever, 我這裏就準備了兩個節點Node1 和 Node2.

wKiom1NNW4STL-LpAAAnHSzcJX8830.jpg

2.更改啓動腳本, 啓動cluster這個模塊 (實際上就是預先配置了一下默認設置,你也可以直接在其他模塊上配置也一樣)

   進入 bin目錄:/apps/cluster_hornetq/node1/bin, 編輯run.sh 更改non-clustered 成clustered.

if [ a"$1" = a ]; then CONFIG_DIR=$HORNETQ_HOME/config/stand-alone/clustered; else CONFIG_DIR="$1"; fi
#if [ a"$1" = a ]; then CONFIG_DIR=$HORNETQ_HOME/config/stand-alone/non-clustered; else CONFIG_DIR="$1"; fi

配置集羣環境:

主要編輯hornetq-configuration.xml.這裏只配置Node1, Node2只需要改變一下端口和連接器名字就好了其他配置相同。

wKioL1NNXIKSqPJGAADtol9uNjM885.jpg

1. 增加與Node2通信的connector.wKiom1NNXRGTLo2tAAJkSq89mqE665.jpg

2.告訴Node1Node2加入到了集羣環境中.

wKioL1NNXaKigDxRAAHSr0hU-5g607.jpg

就這樣分分別配置好Node1和Node2.

Node1: JNDI-port: 1099 , Acceptor-port: 5445

Node2: JNDI-port: 1199 , Acceptor-port: 5465

啓動集羣:

只需要分別啓動兩個節點就好了

測試:

1.測試之前檢查一下隊列裏面的消息,在這裏方便測試。 我把兩個節點的消息全部清空了。

Node1:

wKioL1NNXnLz4mkYAANEmtKnDI0479.jpg

Node2:

wKioL1NNXqii10haAAMHzKXf6Zw767.jpg

2. 發送兩個消息到Node1:

這裏是用到的jndi.properteis, 1099代表Node1,1199代表Node2. 當然Node1是active的時候就會獲取連接工廠從Node1通過JNDI

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://192.168.1.106:1099,jnp://192.168.1.106:1199
#java.naming.provider.url=jnp://192.168.1.106:1199
#java.naming.provider.url=jnp://192.168.1.106:1099

java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

 

Java測試代碼:

package cluster.staticdisc;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.hornetq.api.core.TransportConfiguration;
import org.hornetq.core.client.impl.DelegatingSession;
import org.hornetq.jms.client.HornetQConnection;
public class ProducerTest3 {
/**
* @param args
* @throws NamingException
* @throws JMSException
* @throws InterruptedException
*/
public static void main(String[] args) throws NamingException,
JMSException, InterruptedException {
Context cnx = new InitialContext();
ConnectionFactory cf = (ConnectionFactory) cnx
.lookup("/ConnectionFactory");
Queue queue = (Queue) cnx.lookup("/queue/test1");
Connection initConnection = cf.createConnection();
System.out.println(getServer(initConnection));
Session session = initConnection.createSession();
MessageProducer producer = session.createProducer(queue);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
producer.send(session.createTextMessage("Hello"));
producer.send(session.createTextMessage("Hello"));
initConnection.close();
}
protected static int getServer(Connection connection) {
DelegatingSession session = (DelegatingSession) ((HornetQConnection) connection)
.getInitialSession();
TransportConfiguration transportConfiguration = session
.getSessionFactory().getConnectorConfiguration();
String port = (String) transportConfiguration.getParams().get("port");
return Integer.valueOf(port);
}
}

爲了驗證消息都是發往Node1 (5445) 然後進行服務器集羣的。 我們可以通過netstat -ano 去檢測一下遠程連接的TCP 端口。可以看到只有一個鏈接到5445的TCP 沒有任何鏈接到Node2的。

wKioL1NNYQHR_r_UAAH0CPGopCQ875.jpg

 

接下來檢查一下兩個節點的消息分佈,默認cluster是採用Round-robin 輪訓的策略。

wKioL1NNYX7x4imLAAVRiCqg1Fk666.jpg

到這裏, 靜態配置服務器端集羣就結束了, 太晚了, 下線了。 有任何疑問 請留言!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章