JGroups 初探

最近研究 JAVA 集羣技術,看到 jgroups 這個框架,網上有些例子,很是簡單。
能夠參考其官方網址:http://www.jgroups.org/manual/index.html
按捺不住,本身仍是動手寫了一個試試。代碼以下:

html

  1 import org.jgroups.JChannel;
  2 import org.jgroups.Message;
  3 import org.jgroups.ReceiverAdapter;
  4 import org.jgroups.View;
  5 import org.jgroups.stack.GossipRouter;
  6 
  7 import java.io.BufferedReader;
  8 import java.io.InputStreamReader;
  9 
 10 /**
 11  * JGroups 測試
 12  *
 13  * @author hjj2017
 14  * @since 2016/1/14
 15  *
 16  */
 17 public class HelloJGroups extends ReceiverAdapter { // <-- 注意這裏, HelloJGroups 便是消息的發送者又是消息的接收者
 18     /** 用戶名稱 */
 19     private String _userName = null;
 20     /** JChannel */
 21     private JChannel _channel = null;
 22 
 23     /**
 24      * 開始測試
 25      *
 26      * @throws Exception
 27      *
 28      */
 29     private void start() throws Exception {
 30         // 在這裏生成用戶名, User.00
 31         this._userName = "User." + (int)(Math.random() * 100);
 32 
 33         // 建立 JChannel
 34         this._channel = new JChannel();
 35         this._channel.setReceiver(this);
 36         this._channel.connect("ChatCluster");
 37 
 38         // 事件循環
 39         this.eventLoop();
 40 
 41         // 事件循環結束以後,
 42         // 關閉 JChannel
 43         this._channel.close();
 44     }
 45 
 46     /**
 47      * 事件循環, 從終端讀取文字
 48      *
 49      */
 50     private void eventLoop() {
 51         // 建立讀入流
 52         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 53 
 54         while (true) {
 55             try {
 56                 // 輸出提示符
 57                 System.out.print("~> ");
 58                 System.out.flush();
 59 
 60                 // 從終端讀取文字
 61                 String ln = br.readLine();
 62 
 63                 if (ln.equalsIgnoreCase("quit") ||
 64                     ln.equalsIgnoreCase("exit")) {
 65                     // 遇到 quit / exit 時,
 66                     // 退出當前循環
 67                     break;
 68                 }
 69 
 70                 // 建立併發送消息,
 71                 // 消息內容是 "${userName} : ${ln}"
 72                 Message msg = new Message(null, null, this._userName + " : " + ln);
 73                 this._channel.send(msg);
 74             } catch (Exception ex) {
 75                 // 輸出錯誤日誌
 76                 ex.printStackTrace();
 77             }
 78         }
 79     }
 80 
 81     @Override
 82     public void viewAccepted(View v) {
 83         System.out.println("viewAccepted : " + v);
 84     }
 85 
 86     @Override
 87     public void receive(Message msg) {
 88         System.out.println(msg.getObject());
 89     }
 90 
 91     /**
 92      * 應用程序主函數
 93      *
 94      * @param args
 95      * @throws Exception
 96      *
 97      */
 98     public static void main(String[] args) throws Exception {
 99         new HelloJGroups().start();
100     }
101 }

 

這事一個簡單的聊天程序,能夠啓動兩次來觀察結果。

java

-------------------------------------------------------------------
GMS: address=WINX-HOME-50829, cluster=ChatCluster, physical address=192.168.1.2:52477
-------------------------------------------------------------------
viewAccepted : [WINX-HOME-50829|0] [WINX-HOME-50829]
~> 

-------------------------------------------------------------------
GMS: address=WINX-HOME-1927, cluster=ChatCluster, physical address=192.168.1.2:59569
-------------------------------------------------------------------
viewAccepted : [WINX-HOME-50829|1] [WINX-HOME-50829, WINX-HOME-1927]
~> 


能夠看到,第二個啓動的「WINX-HOME-1927」發現了第一個啓動的「WINX-HOME-50829」。

注意我是在本地測試的,這個程序啓動時會臨時綁定一個端口。

啓動兩次,綁定兩個不一樣的端口,會話過程是在同一臺機器上的兩個不一樣端口之間進行的。

程序啓動以後,這兩個程序會互相發現對方,這是這個框架一個比較方便的地方。

若是是在同一局域網裏的兩臺不一樣的機器上會是什麼結果呢?

我在家裏的兩臺 PC 機上測試過,兩臺 PC 的 IP 地址不相同(192.168.1.2 和 192.168.1.6),

啓動後仍然能夠發現對方!

固然,這裏面有個前提,兩臺機器鏈接着同一臺路由器。

在真實的服務器環境中,全部的服務器都鏈接同一臺路由器是不可能的!

爲此,咱們能夠啓動 GossipRouter,令全部的 JGroups 程序都鏈接到這個 GossipRouter 上。

咱們大概須要作如下 3 步:

1. 啓動 GossipRouter,綁定了 12001 端口:

    java -Djava.net.preferIPv4Stack=true -cp .:commons-logging-1.1.3.jar:log4j-1.2.17.jar:jgroups-2.9.0.GA.jar org.jgroups.stack.GossipRouter -port 12001

2. 建立 myConf.xml 文件,文件內容大體以下:

緩存

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <config xmlns="urn:org:jgroups"
 3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4         xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd">
 5 
 6     <TCP />
 7     <!--// 我試驗過 TCPPING,可是失敗了 //-->
 8     <TCPGOSSIP
 9         timeout="3000"
10         initial_hosts="xxx.xxx.xxx.xxx[12001]" <-- 注意這裏的 xxx.xxx.xxx.xxx 須要換成真實 IP
11         num_initial_members="3"
12     />
13     <VERIFY_SUSPECT timeout="1500"  />
14     <pbcast.NAKACK 
15         use_mcast_xmit="false"
16         retransmit_timeout="300,600,1200,2400,4800"
17         discard_delivered_msgs="true"
18     />
19     <pbcast.STABLE 
20         stability_delay="1000"
21         desired_avg_gossip="50000"
22         max_bytes="400000"
23     />
24     <pbcast.GMS 
25         print_local_addr="true"
26         join_timeout="5000"
27         view_bundling="true"
28     />
29 
30 </config>

 


3. 修改 JChannel 建立代碼,這是最後一步服務器

 

// 只能使用文件絕對路徑, 
// 使用相對路徑, JChannel 會產生歧義
final String xmlAbsPath = ClassLoader.getSystemResource(".").getPath() + "myConf.xml";
this._channel = new JChannel(xmlAbsPath);

 
關於 JGroups,目前我沒有進行「大消息包」和「大集羣量」的測試,還沒法肯定其性能表現。

若是性能方面表現良好,JGroups 放在遊戲項目中,實現跨服聊天、跨服 PK 及分佈式緩存,仍是至關容易的。

併發

相關文章
相關標籤/搜索