ZeroC ICE之旅_weixin_33871366的博客-程序员秘密

技术标签: python  java  c/c++  

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重新启动。

转载于:https://my.oschina.net/pvpCC9IFwqz4/blog/610468

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33871366/article/details/92635622

智能推荐

gson解析json数据分析_gson json解析_何俊灼mn的博客-程序员秘密

GSON是谷歌提供的开源库,用来解析Json格式的数据,非常好用。如果要使用GSON的话,则要先下载gson-2.2.4.jar这个文件,如果是在Android项目中使用,则在Android项目的libs目录下添加这个文件即可;如果是在Java项目中,则把gson-2.2.4.jar先添加到当前项目的任意一个包中,然后右键点击这个jar包 -> 构建路径 -> 添加至构建路径。这样准备工作就做好了

技术分享 | turtlebot3自动驾驶之道路信号检测_阿木实验室的博客-程序员秘密

前言在上一篇文章中,我们介绍了turtlebot3如何检测道路,以便于让其能正确的在道路中央行驶。本文将会介绍turtlebot3在行驶过程中,遇见一些常见的交通信号,例如:红绿灯、转弯等交通标志。1. 理论turtlebot3对交通标志的识别,采用的是 SIFT算法https://docs.opencv.org/master/da/df5/tutorial_py_sift_intro.html详情可以点击这个链接。这里就不再详细叙述。2. T型路口标志检测首先启动仿真环境roslaunch

android 文件关联之mimetype_android mimetype_Burgessb的博客-程序员秘密

很多人都看过在文件管理器中点击一个文件,会弹出很多可供选择的打开方式,如下图:![这里写图片描述](http://img.blog.csdn.net/20170105194855110?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzMyNjEzODY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/

tensorflow中summary操作_dd_summary.image(summary,i)_-牧野-的博客-程序员秘密

tf中 tensorboard 工具通过读取在网络训练过程中保存到本地的日志文件实现数据可视化,日志数据保存主要用到 tf.summary 中的方法。 tf.summary中summary是tf中的一个py文件,位置在 '/tensorflow/python/summary/' 文件夹下,提供了像tf.summary.scalar、tf.summary.histogram 等方法,用来把graph...

Ubuntu上安装Brackets_weixin_33862993的博客-程序员秘密

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

lio linux工具,Linux中三种SCSI target的介绍之LIO_weixin_39796868的博客-程序员秘密

1. 简介Linux-IO Target在Linux内核中(linux 2.6.38后),用软件实现各种SCSI Target,其支持的SAN技术中所有流行的存储协议包括Fibre Channel(Qlogic,linux3.5)、FCoE(linux3.0)、iSCSI(linux 3.1)、iSER (Mellanox InfiniBand,linux3.10), SRP (Mellanox ...

随便推点

放射学中基于影像组学和人工智能预测癌症预后_影像组学与人工智能_思影科技的博客-程序员秘密

人工智能(AI)在医学影像诊断中的成功应用使得基于人工智能的癌症成像分析技术开始应用于解决其他更复杂的临床需求。从这个角度出发,我们讨论了基于人工智能利用影像图像解决临床问题的新挑战,如预测多种癌症的预后、预测对各种治疗方式的反应、区分良性治疗混杂因素与进展,肿瘤异常反应的识别以及突变和分子特征的预测等。我们综述了人工智能技术在肿瘤成像中的发展和机遇,重点介绍了基于人工的影像组学方法和基于深度学习的方法,并举例说明了它们在决策支持中的应用。我们还解决了临床应用过程中面临的挑战,包括数据整理和标注、可解释性以

[Python] NotImplemented 和 NotImplementedError 区别_斜杠老A的博客-程序员秘密

NotImplemented 是一个非异常对象,NotImplementedError 是一个异常对象。>>> NotImplementedNotImplemented>>> NotImplementedErrortype 'exceptions.NotImplementedError'>>>> type(NotImplemented)type 'NotImplementedTy

python之sys模块_python中sys模块_zyc_love_study的博客-程序员秘密

python版本: Python 2.7.6 1: sys是python自带模块. 利用 import 语句输入sys 模块。 当执行import sys后, python在 sys.path 变量中所列目录中寻找 sys 模块文件。然后运行这个模块的主块中的语句进行初始化,然后就可以使用模块了 。2: sys模块常见函数 可以通过dir()方法查看模块中可用的方法. 结果如下, 很

《机器学习实战》学习笔记(六):支持向量机_支持向量机时间怎么这么长_我是管小亮的博客-程序员秘密

专栏【机器学习】【机器学习】《机器学习实战》读书笔记及代码 总目录https://blog.csdn.net/TeFuirnever/article/details/99701256——————————————————————————————————————————————————————目录专栏【机器学习】本章内容1、基于最大间隔分隔数据2、寻找最大间隔3、简化版SMO算法4、利用完...

Windows 7 taskbar and startmenu pin_weixin_33716154的博客-程序员秘密

在Windows 7上,用户可以将自己喜欢的软件“钉”在开始菜单或任务栏,使用起来更加方便。但有时候我们也需要用程序来将这个过程自动化,比如在IT环境里定制客户机,或者我们从一台Win7系统迁移到另一台Win7系统时。 怎么知道已有哪些软件被“钉”在开始菜单或任务栏: 当软件“钉”在开始菜单或任务栏后,系统会在"%appdata%\microsoft\internet explorer\Qui...

推荐文章

热门文章

相关标签