ZeroC ICE之旅

Ice 是 Internet Communications Engine 的簡稱,出自ZeroC名門之下。 
Ice 是一種面向對象的中間件平臺。從根本上說,這意味着Ice 爲構建面向對象的客戶-服務器應用提供了工具、API 和庫支持。Ice 應用適合於異構平臺環境中使用:客戶和服務器能夠採用不一樣的編程語言,能夠運行在不一樣的操做系統和機器架構上,而且可使用多種網絡技術進行通訊。不管部署環境如何,這些應用的源碼都是可移植的。 

其採用C/S 模式結構,支持同步調用方式和異步調用方式,異步派發調用方式。支持跨語言的對象調用。多種語言之間採用共同的Slice(Specification Language for Ice)進行溝通。支持ice到C,JAVA,C#,VB,Python,Ruby,PHP等多種語言的映射。

工欲善其事,必先利其器,咱們首先從www.zero.com,下載最新安裝包; 
btw: 

目前最新的v3.3 
http://www.zeroc.com/download_beta.html 
最新穩定版本: 
http://www.zeroc.com/download.html 


因爲我本身的平臺是CentOS release 4.4 (Final),java version "1.6.0_01" 
因此下載的是: 
http://www.zeroc.com/download/Ice/3.3/Ice-3.3b-rhel4-i386-rpm.tar.gz 

解開以後: 
-rw-r--r--  1 506 users 1130231  4月  1 10:39 db46-4.6.21-2ice.rhel4.i386.rpm 
-rw-r--r--  1 506 users   51459  4月  1 10:39 db46-devel-4.6.21-2ice.rhel4.i386.rpm 
-rw-r--r--  1 506 users  810562  4月  1 10:40 db46-java-4.6.21-2ice.rhel4.i386.rpm 
-rw-r--r--  1 506 users   72125  4月  1 10:40 db46-utils-4.6.21-2ice.rhel4.i386.rpm 
-rw-r--r--  1 506 users   84281  4月  1 10:15 ice-3.3b-1.rhel4.noarch.rpm 
-rw-r--r--  1 506 users  450359  4月  1 10:15 ice-c++-devel-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users 2823701  4月  1 10:16 ice-java-3.3b-1.rhel4.noarch.rpm 
-rw-r--r--  1 506 users  263085  4月  1 10:16 ice-java-devel-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users 3439061  4月  1 10:17 ice-libs-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users  162092  4月  1 10:19 ice-php-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users  739055  4月  1 10:19 ice-python-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users   32913  4月  1 10:19 ice-python-devel-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users  223577  4月  1 10:19 ice-ruby-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users   21406  4月  1 10:19 ice-ruby-devel-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users 3657167  4月  1 10:20 ice-servers-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users 4350193  4月  1 10:24 ice-utils-3.3b-1.rhel4.i386.rpm 
-rw-r--r--  1 506 users   74856  4月  1 10:40 mcpp-devel-2.6.4-1ice.rhel4.i386.rpm 
因爲須要c和java的包: 
因此咱們僅安裝: 
rmp -ivh ice-3.3b-1.rhel4.noarch.rpm 
rmp -ivh ice-3.3b-1.rhel4.noarch.rpm 
rpm -ivh ice-3.3b-1.rhel4.noarch.rpm 
rpm -ivh ice-libs-3.3b-1.rhel4.i386.rpm 
rpm -ivh ice-utils-3.3b-1.rhel4.i386.rpm 
rpm -ivh mcpp-devel-2.6.4-1ice.rhel4.i386.rpm 
rpm -ivh ice-servers-3.3b-1.rhel4.i386.rpm 
rpm -ivh ice-libs-3.3b-1.rhel4.i386.rpm 
rpm -ivh ice-c++-devel-3.3b-1.rhel4.i386.rpm 
rpm -ivh ice-java-3.3b-1.rhel4.noarch.rpm 
rpm -ivh ice-java-devel-3.3b-1.rhel4.i386.rpm 

安裝以後的Ice相關路徑: 
slice2cpp,slice2java在/usr/bin/下 
Ice.jar 存儲於 /usr/share/java/下 
相關的Ice的庫存儲於/usr/lib下. 

一切就緒,咱們開始Ice之旅的Slice地帶: 
首先,咱們創建一個demo.ice的文件: 

Java代碼  
  1. module Demo{  
  2. interface test{  
  3.  string   execute(string mth,string cmd);  
  4. };  
  5. };  


注意,後兩個"}"必定要包含";",不然slice2java就會過不去,赫赫 
執行: 
slice2java demo.ice 

會在當前目錄產生一個Demo目錄,目錄下自動生成: 
-rw-r--r--  1 root root 2316  4月 15 17:01 _testDelD.java 
-rw-r--r--  1 root root  560  4月 15 17:01 _testDel.java 
-rw-r--r--  1 root root 1929  4月 15 17:01 _testDelM.java 
-rw-r--r--  1 root root 4177  4月 15 17:01 _testDisp.java 
-rw-r--r--  1 root root 1070  4月 15 17:01 testHolder.java 
-rw-r--r--  1 root root  488  4月 15 17:01 test.java 
-rw-r--r--  1 root root  481  4月 15 17:01 _testOperations.java 
-rw-r--r--  1 root root  460  4月 15 17:01 _testOperationsNC.java 
-rw-r--r--  1 root root 5418  4月 15 17:01 testPrxHelper.java 
-rw-r--r--  1 root root  569  4月 15 17:01 testPrxHolder.java 
-rw-r--r--  1 root root  567  4月 15 17:01 testPrx.java 
到目前爲止,demo.ice因此Ice接口部分的定義以及相關依賴都已經自動生成. 

咱們要實現本身的execute方法,覆蓋testPrx.java的同名方法: 
Java代碼  
  1. //TestImp.java  
  2. package Demo;  
  3.   
  4. import Ice.Current;  
  5.   
  6.   
  7. public class TestImp extends _testDisp{  
  8.   
  9.     public String execute(String mth, String cmd, Current __current) {  
  10.         // TODO Auto-generated method stub  
  11.         return mth+cmd;  
  12.     }  
  13.   
  14.   
  15.   
  16. }  
看到了,就是這麼簡單,僅僅覆蓋_testDisp裏面的抽象方法,實現把咱們本身的實現代碼填充到裏面就好了. 
以後,咱們創建一個Server服務在10000端口進行偵聽。 
Java代碼  
  1. //Server.java  
  2. package Demo;  
  3.   
  4. public class Server {  
  5.     public static void main(String[] args) {  
  6.         int status = 0;  
  7.         Ice.Communicator ic = null;  
  8.         try {  
  9.             ic = Ice.Util.initialize(args);  
  10.             Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints(  
  11.                     "TestAdapter""default -p 10000");  
  12.             Ice.Object object = new TestImp();  
  13.             adapter.add(object, ic.stringToIdentity("TestAdapter"));  
  14.             adapter.activate();  
  15.             ic.waitForShutdown();  
  16.         } catch (Ice.LocalException e) {  
  17.             e.printStackTrace();  
  18.             status = 1;  
  19.         } catch (Exception e) {  
  20.             System.err.println(e.getMessage());  
  21.             status = 1;  
  22.         }  
  23.         if (ic != null) {  
  24.             // Clean up  
  25.             //  
  26.             try {  
  27.                 ic.destroy();  
  28.             } catch (Exception e) {  
  29.                 System.err.println(e.getMessage());  
  30.                 status = 1;  
  31.             }  
  32.         }  
  33.         System.exit(status);  
  34.     }  
  35. }  

貌似很複雜,其實裏面的不少內容都是固定格式,有些部分須要固定和約定。其中上述紅色部分是修改部分。 

到目前爲止,咱們已經完成了大部分工做,咱們還須要建一個客戶端來對服務端的方法進行調用。 
Java代碼  
  1. package Demo;  
  2.   
  3. public class Client {  
  4.     public static void main(String[] args) {  
  5.         int status = 0;  
  6.         Ice.Communicator ic = null;  
  7.         try {  
  8.             ic = Ice.Util.initialize(args);  
  9. //          Ice.ObjectPrx base = ic  
  10. //                  .stringToProxy("SimplePrinter:tcp -h 172.17.12.101 -p 10000");  
  11.             Ice.ObjectPrx base = ic  
  12.             .stringToProxy("TestAdapter:default -p 10000");  
  13.   
  14.             testPrx test = testPrxHelper.checkedCast(base);  
  15.             if (test == null)  
  16.                 throw new Error("Invalid proxy");  
  17.             System.out.println(test.execute("My first Ice ""demo"));  
  18.             //System.out.println("ok");  
  19.         } catch (Ice.LocalException e) {  
  20.             e.printStackTrace();  
  21.             status = 1;  
  22.         } catch (Exception e) {  
  23.             System.err.println(e.getMessage());  
  24.             status = 1;  
  25.         }  
  26.         if (ic != null) {  
  27.             // Clean up  
  28.             //  
  29.             try {  
  30.                 ic.destroy();  
  31.             } catch (Exception e) {  
  32.                 System.err.println(e.getMessage());  
  33.                 status = 1;  
  34.             }  
  35.         }  
  36.         System.exit(status);  
  37.     }  
  38. }  


也貌似很複雜吧,其實否則,也很簡單,一樣包含不少固定格式。其中 

Java代碼  
  1. System.out.println(test.execute("my first Ice ""demo"));  


是咱們本身調用的邏輯。 

赫赫,大功告成了,如今咱們開始運行Server,再運行Client看到了麼? 
"My first Ice demo" 

獲得這樣的結果,基本Ice之旅的Java部分簡單實例咱們基本完成。 

Ice的性能和穩定性遠超於咱們的想象,skype知道麼?其部分通信架構就是採用的Ice. 

ZeroC ICE之旅------Slice

 Slice是在ICE所特有的特殊語言,ICE 提供基於Ice語言的多語言映射工具。Slice主要針對程序所涉及到的接口和類型進行定義。不涉及到具體實現和具體語言的特徵。 
   既然ICE支持跨語言的調用,那麼是否是Slice支持每種的特有數據類型呢? 
   固然不是,ICE只是保留各類具體語言數據類型的最小交集。 
提供: 
Java代碼  
  1. 1.bool (false or true,>=1bit)  
  2. 2.byte (-128-127@,>=8bits)  
  3. 3.short (-2^15 to 2^15-1,>=16bits)  
  4. 4.int (-2^31 to 2^31-1,>=32bits)  
  5. 5.long (-2^63 to 2^63-1,>=64bits)  
  6. 6.float (IEEE single-precision,>=32bits)  
  7. 7.double (IEEE double-precision,>=64bits)  
  8. 8.string (All Unicode characters, excluding ,the character with all bits zero.)  


string 採用Unicode編碼,具備很好的國際化語言支持。 

下面主要在介紹一下Slice的特性和約束: 
1. Slice文件必須以.ice結尾,其餘結尾方案的文件會被編譯器拒絕。 
2. Slice 文件格式實際就是text文本描述,因爲Slice形式自由,能夠用任何文本編輯器進行編輯。 
3. Slice 支持#ifndef,#define,#endif,#include 
例如: 
Java代碼  
  1. // File Clock.ice  
  2. #ifndef _CLOCK_ICE  
  3. #define _CLOCK_ICE  
  4. // #include directives here...  
  5. // Definitions here...  
  6. #endif _CLOCK_ICE  

在include 要避免使用雙引號"",以及"",而要使用"/" 
例如: 
#include "Clock.ice" // 不推薦採用; 
#include <SliceDefs/Clock.ice> // 正確 
#include <SliceDefs\Clock.ice> // 非法 
4.Slice 中文件的結構,模塊,接口,類型出現的順序,,能夠按照你的喜愛而自由定義。 
5.Slice 的詞法規則不少來源於C++和Java,只有少許的差別。 
6.能夠採用c++的註釋規則。// 或  
7.Slice 的關鍵詞須要區分大小寫: 
關鍵詞: 
Java代碼  
  1. bool        enum        implements      module      struct  
  2. byte        exception   int         Object      throws  
  3. class       extends     interface       out     true  
  4. const       false       local           sequence    void  
  5. dictionary  float       LocalObject     short  
  6. double      idempotent  long            string  
8.在接口定義的時候也避免使用非Slice關鍵字,可是C++ 或 Java關鍵字的標識符。 

例如:switch 

9.Ice保留了全部以"ice"做爲開始標識符。保留以"Helper","Holder","Prx","Ptr"結尾的標識符。因此你們定義的時候最好避免一些沒必要要的麻煩。 

10.Ice能夠經過module嵌套的方式,相似於c++的namespace和java的包的概念。 


11.除了剛纔提到的Slice支持的基礎類型外,還支持用戶自定義類型:enumerations, structures, sequences, and dictionaries. 

enumerations:枚舉就不要介紹了,採用C++的語法形式 
enum Fruit { Apple, Pear, Orange }; 

Structures:結構,也是採用C++的語法形式,避免,結構中定義結構 
Java代碼  
  1. 合法:  
  2. struct TimeOfDay {  
  3. short hour; // 0 - 23  
  4. short minute; // 0 - 59  
  5. short second; // 0 - 59  
  6. };  
  7. 無效:  
  8. struct TwoPoints {  
  9. struct Point { // Illegal!  
  10. short x;  
  11. short y;  
  12. };  
  13. Point coord1;  
  14. Point coord2;  
  15. };  

sequence:序列號類型,映射到java採用的數組方式實現,而不是所謂的集合容器類型對象存儲。映射到C++中則採用STL容器存儲。 
sequence<int> values; 
dictionary:字典類型,映射到java採用Map 進行存儲,映射到C++採用map進行存儲. 
dictionary<int,string> myValues; 
12.常量定義能夠直接使用,但常量的定義必須是基本類型或枚舉類型.定義形式也是採用C++定義方式. 
13.方法的定義,形式類型java的方法定義,方法返回可使void或對象類型. 
14.Slice支持方法異常的定義,以及異常的繼承.關於異常機制,我想java開發者可能更加熟悉, 
例如: 
Java代碼  
  1. exception Error {}; // Empty exceptions are legal  
  2. exception RangeError {  
  3. TimeOfDay errorTime;  
  4. TimeOfDay minTime;  
  5. TimeOfDay maxTime;  
  6. };  
  7. interface Clock {  
  8. idempotent TimeOfDay getTime();  
  9. idempotent void setTime(TimeOfDay time)  
  10. throws RangeError, Error;  
  11. };  

Ice的錯誤機制也是異常強大,吸收了不少Java關於異常機制的特色. 


Slice還包括不少良好的特性,在這裏就不一一列舉,對於支持自定義類型,基本類型,異常支持,對於通常的網絡通信應用已經足夠了,更多Slice語言的介紹參閱其幫助. 

Ice爲咱們提供了強大而又豐富的Slice,能夠利用Slice,結合咱們應用的特色,定義間接的Slice描述。 

btw: 

    雖然Slice提供給咱們豐富的功能和特性,在此我仍是建議你們儘可能採用基本類型和非異常機制.這樣會對系統性能會帶有必定的幫助。 
    另外接口的定義我想你們可以保持KISS(Keep it It Simple)設計原則,會使咱們的應用看起來更美麗。 
    不要過分的使用Slice,不然會給咱們帶來無盡的煩惱。 

ZeroC ICE之旅------多語言互通互聯

ce的服務端能夠採用C++/Java/Python/C#等實現,客戶端能夠採用C++/Java/Python/C#/VB/PHP/Ruby來實現,就是說個人一個服務端採用C++實現,客戶端能夠採用java/php/vb/c# 等其餘語言實現。 

這個特性也是Ice的很重要的優點之一. 

Ice的多語言之間如何確保對象的正確傳輸,每種語言都有各自的特色,數據類型,Ice是如何達到各類語言之間的互通互聯的呢? 
那麼就必定提到Slice語言.Slice是保證各類語言的互通互聯的關鍵,它是獨立於其它任何語言,Ice能夠經過把Slice代碼片段轉化爲各自的 

語言描述. 

Java代碼  
  1. -rwxr-xr-x  1 system users 447888 2007-03-09  slice2java  
  2. -rwxr-xr-x  1 system users  67753 2007-03-09  slice2py  
  3. -rwxr-xr-x  1 system users  38679 2007-03-09  slice2rb  
  4. -rwxr-xr-x  1 system users 505441 2007-03-09  slice2vb  
  5. -rwxr-xr-x  1 system users 507119 2007-03-09  slice2cpp  
  6. -rwxr-xr-x  1 system users 454347 2007-03-09  slice2cs  


赫赫夠多! 

Slice的全稱:Specification Language for Ice,是Ice本身的特殊語言,一種用於使對象接口與其實現相分離的基礎性抽象機制。Slice 創建在客戶與服務器之間的合約,用以描述應用所使用的類型和對象接口。Slice描述獨立於實現語言,因此客戶實現語言是否與編寫服務器所用的語言相同沒有任何關係。 

slice語言片斷能夠被編譯爲任何所支持語言的實現。目前Ice Slice能夠支持映射到到C++, Java, C#, Python,Ruby, and PHP。 
由於Slice主要對接口和類型的定義和描述,沒有實現部分。 

到底如何實現不一樣語言的互通互聯的呢?咱們已Java,C++做爲Ice例子原形,實際上咱們僅僅作少許修改,就能夠實現 

C++的服務端,Java的客戶端。Server和Client仍是保持在同一臺機器上運行。注意咱們基於同一個demo.ice的事例。 

首先運行./Server,再運行Client,看到結果了麼?赫赫,是否是出現了正常結果。 

到目前沒有咱們全部實例都是基於同一臺機器的,實際狀況Server,Client會分佈在不一樣機器上。這種狀況下,咱們須要如何處理呢? 


這個很簡單,在Server少許修改 
Java代碼  
  1. Ice::ObjectAdapterPtr adapter  =   ic->createObjectAdapterWithEndpoints ("TestAdapter",                                "default -p 10000");  


"default -p 10000" 採用 "tcp -h server1 -p port" 替代 

Server所在主機IP:172.17.12.101 ,端口:10000 

因此就修改成:tcp -h 172.17.12.101 -p 10000,再從新編譯Server 

Java代碼  
  1. #include <Ice/Ice.h>  
  2. #include <demo.h>  
  3. using namespace std;  
  4. using namespace Demo;  
  5. class Server:public test  
  6. {  
  7. public:  
  8.   ::std::string execute (const string & mth, const string & str,  
  9.                          const Ice::Current &);  
  10. public:  
  11.     Server ();  
  12. };  
  13. Server::Server ()  
  14. {  
  15.    
  16. };  
  17. std::string Server::execute (const string & mth, const string & str,  
  18.                              const Ice::Current &)  
  19. {  
  20.   cout << mth + str << endl;  
  21.   return mth + str;  
  22. }  
  23.    
  24. int  
  25. main (int argc, char *argv[])  
  26. {  
  27.   int  
  28.     status = 0;  
  29.   Ice::CommunicatorPtr ic;  
  30.   try  
  31.   {  
  32.     ic = Ice::initialize (argc, argv);  
  33.     Ice::ObjectAdapterPtr adapter  
  34.       =  
  35.       ic->createObjectAdapterWithEndpoints ("TestAdapter",  
  36.                                             "tcp -h 172.17.12.101 -p 10000");  
  37.     Ice::ObjectPtr object = new Server;  
  38.     adapter->add (object, ic->stringToIdentity ("TestAdapter"));  
  39.     adapter->activate ();  
  40.     ic->waitForShutdown ();  
  41.   } catch (const Ice::Exception & e)  
  42.   {  
  43.     cerr << e << endl;  
  44.     status = 1;  
  45.   } catch (const char *msg)  
  46.   {  
  47.     cerr << msg << endl;  
  48.     status = 1;  
  49.   }  
  50.   if (ic)  
  51.     {  
  52.       try  
  53.       {  
  54.         ic->destroy ();  
  55.       }  
  56.       catch (const Ice::Exception & e)  
  57.       {  
  58.         cerr << e << endl;  
  59.         status = 1;  
  60.       }  
  61.     }  
  62.   return status;  
  63. }  

編譯方式參見: 
http://masterkey.iteye.com/blog/183307 

下面咱們須要對Client鏈接部分進行修改,同理: 
Java代碼  
  1. Ice.ObjectPrx base = ic.stringToProxy("TestAdapter:tcp -h 172.17.12.101 -p 10000");  


Java代碼  
  1. package Demo;  
  2.   
  3. public class Client {  
  4.     public static void main(String[] args) {  
  5.         int status = 0;  
  6.         Ice.Communicator ic = null;  
  7.         try {  
  8.             ic = Ice.Util.initialize(args);  
  9. //          Ice.ObjectPrx base = ic  
  10. //                  .stringToProxy("SimplePrinter:tcp -h 172.17.12.101 -p 10000");  
  11.             Ice.ObjectPrx base = ic  
  12.             .stringToProxy("TestAdapter:tcp -h 172.17.12.101 -p 10000");  
  13.   
  14.             testPrx test = testPrxHelper.checkedCast(base);  
  15.             if (test == null)  
  16.                 throw new Error("Invalid proxy");  
  17.             System.out.println(test.execute("My first Ice ""事例"));  
  18.             //System.out.println("ok");  
  19.         } catch (Ice.LocalException e) {  
  20.             e.printStackTrace();  
  21.             status = 1;  
  22.         } catch (Exception e) {  
  23.             System.err.println(e.getMessage());  
  24.             status = 1;  
  25.         }  
  26.         if (ic != null) {  
  27.             // Clean up  
  28.             //  
  29.             try {  
  30.                 ic.destroy();  
  31.             } catch (Exception e) {  
  32.                 System.err.println(e.getMessage());  
  33.                 status = 1;  
  34.             }  
  35.         }  
  36.         System.exit(status);  
  37.     }  
  38. }  

看到了麼,就是這麼簡單,其餘部分不用修改。 

好了,咱們進行驗證,首先啓動./Server,再執行Client ,看到了 

"My first Ice 事例" 看到了麼,祝賀你,跨語言的分佈式調用例子你已經實現了。 


其實Ice的通信機制極其強大,支持集羣和容錯技術。關於集羣的事例會在往後的文章中介紹。 

BTW: 

注意,Server運行以後監聽於10000端口,須要修改iptables,容許其餘機器能夠鏈接。 
編輯 iptables 
vi /etc/sysconfig/iptables 
追加: 
Java代碼  
  1. -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 10000 -j ACCEPT  


Zero ICE咱們已經掌握其基本運行原理。下面咱們主要介紹一下ICe的多端口邦定的問題。  ICE使用TCP/IP 和UDP協議,以及基於TCP/IP之上的SSL協議。SSL協議能夠充分保障Server/Client數據傳輸的加密安全性問題。  在這裏,Server如何在同一臺主機監聽多個端口。  關於TCP/IP仍是UDP仍是SSL協議的選擇,仍是要看具備應用的要求,一般狀況下TCP/IP協議的ICE應用已經足夠了。  在同一個主機主機上,ICE服務支持多端口的監聽。  服務端註冊: tcp -h host -p port1:tcp -h host -p port2形式,  例如:  IP:172.17.12.101,須要在10001和10000同時監聽。  就能夠寫成:  tcp -h 172.17.12.101 -p 10000:tcp -h 172.17.12.101 -p 10001  赫赫是否是很簡單,運行以後,服務就監聽於10000和10001端口,請注意:避免其餘應用相沖突。  客戶端鏈接能夠採用以下3種形式:  1. tcp -h 172.17.12.101 -p 10000  2. tcp -h 172.17.12.101 -p 10001  3. tcp -h 172.17.12.101 -p 10000:tcp -h 172.17.12.101 -p 100001  是否是很爽。  不管Server監聽在多個端口,仍是隻有惟一的一個Server在工做,  對於Client較多的應用或負載要求很高的狀況下,咱們能夠把Server程序運行於多臺主機之上。經過集羣方式合理有效的化解來自Client的壓力。  例如:  ServerA 172.17.12.101 tcp -h 172.17.12.101 -p 10000  ServerB 172.17.12.102 tcp -h 172.17.12.102 -p 10000  ServerC 172.17.12.103 tcp -h 172.17.12.103 -p 10000  Client能夠以下的鏈接方式:  tcp -h 172.17.12.101 -p 10000:tcp -h 172.17.12.102 -p 10000:tcp -h 172.17.12.103 -p 10000  或是  tcp -h 172.17.12.101 -p 10000:tcp -h 172.17.12.102 -p 10000  等多種狀況,能夠根據應用的具體要求合理有效的構造所需鏈接主機的字符串。  這種鏈接方式是否是很cool。  其實這種鏈接方式能夠有效地利用ICE提供的load balancing功能,把Client的每一個請求合理的分配到每一個Server。從而有效地避免了Client大量請求對同一臺Server的巨大壓力。  ICE的load balancing主要採用round-robin算法,round-robin是一種很是有效的負載均衡算法.  你們會問了,若是某個Server若是宕機,那麼這個Client還能正常工做麼?      這個問題問得好,其實ICE自身提供一種極其強大容錯技術功能。      具體體如今若是當某個Server(假設是ServerA)宕機以後,來自Client的請求分配到ServerA服務器上,Client會自動記錄ServerA失效狀態,會把請求再分配給可正常工做的Server(ServerB,ServerC),對於用戶的每次請求都能分配到正常的服務主機上(除非A,B,C都同時宕機).當ServerA回覆正常以後,Client會自動感知ServerA工做狀態.Client的請求又能夠有效地分配到上述A,B,C主機上.這一切對於開發者都是透明的.  ICE所提供的集羣功能和容錯功能是極其強大的.     Client狀態感知的變化和更新徹底不須要Client從新啓動。
相關文章
相關標籤/搜索