2005年01月08日
Summary

这里介绍了ICE的五个服务

        Ice为分布式开发提供了技术完善的客户-服务平台。实际上,现实的应用不仅仅只需要具备远程通讯能力,通常的,还需要随需启动服务,把代理分布到客户端,分发异步事件,配置应用,发布补丁等等。


        Ice自带了一些服务,这些服务具备了上面所说的特征和一些其它的特征。这些服务实现以服务器的形式实现并向你的应用提供服务。他们分别是:


1、IcePack


         IcePack是Ice的定位服务。当使用间接绑定时,用来将符号化的适配器名称转换为协议-地址对。除了定位服务之外,IcePack还提供了如下的服务:


  • IcePack允许你注册一个自动启动的服务:即当客户端进行请求时,服务器不需要处于运行状态,只要第一个客户端进行请求时,服务会自动启动。
  • IcePack支持脚本描述部署,可以轻易的配置包含了若干个服务的复杂的应用
  • IcePack提供了简单的对象查找服务,允许客户端获取他们感兴趣的对象代理。


2、IceBox


        IceBox是一个简单的应用服务器,它可以协调多个应用组件启动和停止。


        应用组件可以用动态链接库的形式发布而不是一个进程。这就减轻了系统的负载。例如,你可以在一个JVM中运行若干个应用组件而不是有多个进程,每一个进程都有自己的JVM。


3、IceStorm


        IceStorm是一个发布-订阅服务,它减除了客户端和服务器的耦合度。本质上说,IceStorm作为一个事件分发的交换机运行。发布者将事件发给服务,IceStorm按照顺序将事件传递给订阅者。使用这种方法,一个事件发布者就可以把一个事件发布给多个订阅者。事件按照主题分类,订阅者可以指定他们感兴趣的主题。只有订阅者感兴趣的主题才会发送给订阅者。服务允许指定服务的质量,从而允许应用在可伸缩性和性能之间进行适当的折中。


        如果你需要将信息发布到大量的应用组建,那么IceStorm是一个不错的选择。(一个很典型的例子就是股票报价的应用)。IceStorm减除了信息的发布者和订阅者之间的耦合,同时也能重新发布已经发布的信息。另外,IceStorm可以作为联合服务运行,即多个服务的实例可以运行在不同的机器上,从而降低了CPU的负载。


4、IcePatch


        IcePatch是一个软件补丁服务。它允许你轻松的把软件的更新发布给客户。客户连接到IcePatch然后请求更新一个特定的应用。服务就自动检查客户软件的版本然后下载需要更新的组件。而这些下载的组件都是放在一个压缩包里的,从而减少了带宽的占用。软件补丁也可以通过结合Glacier服务发布,这样可以让只有经过授权的客户才能下载软件更新。


5、Glacier


        Glacier是Ice防火墙服务:它允许客户和服务器通过防火墙安全的通讯。客户-服务器的通讯通过使用公钥认证完全加密,并且通讯是双向的。Glacier提供了相互认证和安全的会话管理支持。


2004年11月20日

原文来自blogCentaur 随笔录使用C#编写Ice应用程序,原文程序中没有注释,我参照马维达翻译的ICE分布式程序设计Ice-1.3.0-C.pdf,里面的代码有C++和Java的,没有C#的,计划平时有空学习ICE的C#程序设计,将相应的代码使用C#编写,算是学习ICE吧,今天第一个程序就是HelloWord应用:
C#开发环境的搭建参照使用C#编写Ice应用程序。补充一点是设置Path目录中增加ice-1.5.1和增加环境变量ICE_HOME




1、编写任何Ice 应用的第一步都是要编写一个Slice 定义,其中含有应用所


用的各个接口。我们为我们的小打印应用编写了这样的Slice 定义:


Hello World 应用


interface Printer


{


void printString(string s);


};


我们把这段文本保存在叫作Printer.ice 的文件中。


我们的Slice 定义含有一个接口,叫作Printer。目前,我们的接口非常简单,只提供了一个操作,叫作printStringprintString 操作接受一个串作为它唯一的输入参数;这个串的文本将会出现在(可能在远地的)打印机上。

2、编写用于C# Slice 定义

要创建我们的C# 应用,第一步是要编译我们的Slice 定义,生成C#代理和骨架。在Windows上,你可以这样编译定义:


slice2cs.exe Printer.ice


slice2cs 编译器根据这个定义生成一些.cs 源文件。我们目前无需关注这些文件的确切内容——它们包含的是编译器生成的代码,与我们在Printer.ice 中定义的Printer 接口相对应。


3、编写和编译服务器


要实现我们的Printer 接口,我们必须创建一个servant 类。按照惯例,


servant 类的名字是它们的接口的名字加上一个I 后缀,所以我们的servant


类叫作PrinterI,并放在PrinterI.cs 源文件中:


using System;


 


namespace IceTest


{


     /// <summary>


     /// 要实现我们的Printer 接口,我们必须创建一个servant 类。按照惯例,


     ///servant 类的名字是它们的接口的名字加上一个I 后缀,所以我们的servant


     ///类叫作PrinterI,PrinterI 类继承自叫作_PrinterDisp 的基类。这个基类由


     ///slice2cs 编译器生成,是一个抽象类,其中含有一个printString


     ///方法,其参数是打印机要打印的串,以及类型为Ice.Current 的对象


     ///我们的printString 方法的实现会简单地把它的参数写到终端。


     /// </summary>


     public class PrinterI :_PrinterDisp


     {


         public PrinterI()


         {


              //


              // TODO: 在此处添加构造函数逻辑


              //


         }


 


         public override void printString(string s, Ice.Current __current)


         {


             System.Console.WriteLine(s);


         }


     }


}


PrinterI 类继承自叫作_PrinterDisp 的基类。这个基类由slice2cs 编译器生成,是一个抽象类,其中含有一个printString方法,其参数是打印机要打印的串,以及类型为Ice.Current 的对象.我们的printString 方法的实现会简单地把它的参数写到终端。


服务器代码的其余部分在一个叫作Server.cs 的源文件中,下面给出了其完整代码:


using System;


namespace IceTest


{


     /// <summary>


     /// Server 的摘要说明。


     /// </summary>


     public class Server


     {


         public Server()


         {


              //


              // TODO: 在此处添加构造函数逻辑


              //


         }


 


         public static void Main(string[] args)


         {


              int status = 0;


              Ice.Communicator ic = null;


              try


              {


                   //初始化Ice runtime ,将args传递给这个调用,是因为服务器可能


                   //有run time感兴趣的命令行参数,返回的是一个Ice.Communicator


                   //它是Ice run time的主句柄


                   ic = Ice.Util.initialize(ref args);


                   //调用createObjectAdapterWithEndpoints创建一个对象适配器,传入的参数为SimplePrinter(适配器名称)


                   //和default -p 10000或者是适配器使用缺省协议TCP/IP在端口10000侦听到来的请求


                   Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints(“SimplePrinter”,”default -p 10000″);


                //这时,服务器端run time 已经初始化,我们实例化一个PrinterI 对


                //象,为我们的Printer 接口创建一个servant。


                   Ice.Object obj = new PrinterI();


                   //我们调用适配器的add,告诉它有了一个新的servant ;传给add 的参


                //数是我们刚才实例化的servant,再加上一个标识符。在这里,


                //”SimplePrinter” 串是servant 的名字(如果我们有多个打印机,每个


                //打印机都会有不同的名字,更正确的说法是,都会有不同的对象标识)。


                   adapter.add(


                        obj,Ice.Util.stringToIdentity(“SimplePrinter”));


                   //我们调用适配器的activate 方法激活适配器(适配器一开


                //始是在扣留(holding)状态创建的;这种做法在下面这样的情况下很


                //有用:如果我们有多个servant,它们共享同一个适配器,而在所有


                //servant 实例化之前我们不想处理请求)。一旦适配器被激活,服务器就


                //会开始处理来自客户的请求。


                   adapter.activate();


                   //调用waitForShutdown。这个方法挂起发出调用的线程,


                //直到服务器实现终止为止——或者是通过发出一个调用关闭run time,


                //或者是对某个信号作出响应(目前,当我们不再需要服务器时,我们


                //会简单地在命令行上中断它)。


                   ic.waitForShutdown();


              }


              catch (Exception e)


              {


                   Console.Error.WriteLine(e);


                   status = 1;


              }


              finally


              {


                   if (ic != null)


                        ic.destroy();


              }


              Environment.Exit(status);


         }


     }


}


Main 的主体含有一个try 块,我们把所有的服务器代码都放在其中;然后是两个catch 处理器。第一个处理器捕捉Ice run time 可能抛出的所有异常,其意图是,如果代码在任何地方遇到意料之外的Ice 运行时异常,栈会一直退回到Main,打印出异常,然后把失败返回给操作系统。第二个处理器捕捉串常量,其意图是,如果我们在代码某处遇到致命错误,我们可以简单地抛出带有出错消息的串文本。这也会使栈退回到main,打印出出错消息,然后把失败返回给操作系统。


这段代码会在退出之前销毁通信器(如果曾经成功创建过)。要使Ice run time 正常结束,这样做是必需的:程序必须调用它所创建的任何通信器的destroy ;否则就会产生不确定的行为。我们把对destroy 的调用放进finally 块,这样,不管前面的try 块中发生什么异常,通信器都保证会正确销毁。


4、编写和编译客户


客户代码在Client.cs 中,看起来与服务器非常类似。下面是完整


的代码:


using System;


 


namespace IceClientTest


{


     /// <summary>


     /// Client 的摘要说明。


     /// </summary>


     public class Client


     {


         public Client()


         {


              //


              // TODO: 在此处添加构造函数逻辑


              //


         }


 


         public static void Main(string[] args)


         {


              int status = 0;


              Ice.Communicator ic = null;


              try


              {


                   //调用Ice::initialize 初始化Ice run time。


                   ic = Ice.Util.initialize(ref args);


                   //获取远地打印机的代理。我们调用通信器的stringToProxy


                //创建一个代理,所用参数是”SimplePrinter:default -


                //p 10000″。注意,这个串包含的是对象标识和服务器所用的端口号


                   Ice.ObjectPrx obj = ic.stringToProxy(


                        “SimplePrinter:default -p 10000″);


                   //stringToProxy 返回的代理的类型是Ice::ObjectPrx,这种类型


                //位于接口和类的继承树的根部。但要实际与我们的打印机交谈,我们需


                //要的是Printer 接口、而不是Object 接口的代理。为此,我们需要调


                //用PrinterPrxHelper.checkedCast 进行向下转换。这个方法会


                //发送一条消息给服务器,实际询问“这是Printer 接口的代理吗?”如


                //果是,这个调用就会返回Printer 的一个代理;如果代理代表的是其他


                //类型的接口,这个调用就会返回一个空代理。


                   PrinterPrx printer


                       = PrinterPrxHelper.checkedCast(obj);


                   //测试向下转换是否成功,如果不成功,就抛出出错消息,终止客户。


                   if (printer == null)


                       throw new ApplicationException(“Invalid proxy”);


                   //我们的地址空间里有了一个活的代理,可以调用printString 方法,


                   //把享誉已久的 “Hello World!” 串传给它。服务器会在它的终端上打印这个串。


                   printer.printString(“Hello World!”);


              }


              catch (Exception e)


              {


                   Console.Error.WriteLine(e);


                   status = 1;


              }


              finally


              {


                   if (ic != null)


                        ic.destroy();


              }


              Environment.Exit(status);


         }


     }


}


 


 


Ice (Internet Communications Engine)是由前CORBA专家Marc Laukien、Michi Henning及Matthew Newhook等人开发的新一代面向对象中间件,已被用作大型在线游戏Wish(www.wishgame.com) 的通信引擎。关于Ice的详细介绍,可参考以下资料:

* 《反叛之冰:Internet Communications Engine》 – http://blog.csdn.net/grhunter/archi…7/20/45606.aspx

* 《ICE之父抵京讲解高性能网络计算引擎》 – http://www.csdn.net/news/newstopic/16/16366.shtml

* 2004年第9期《程序员》杂志上的Ice专题 – http://mag.csdn.net/Content.aspx?ID…dd-0b3e55740577