消息与.Net Remoting的分布式处理架构
一、消息的定义
要实现进程间的通信,则通信内容的载体——消息,就必须在服务两端具有统一的消息标准定义。从通信的角度来看,消息可以分为两类:Request Messge和Reply Message。为简便起见,这两类消息可以采用同样的结构。
消息的主体包括ID,Name和Body,我们可以定义如下的接口方法,来获得消息主体的相关属性:
消息主体类Message实现了IMessage接口。在该类中,消息体Body为IMessageItemSequence类型。这个类型用于Get和Set消息的内容:Value和Item:
Value为string类型,并利用HashTable来存储Key和Value的键值对。而Item则为IMessageItem类型,同样的在IMessageItemSequence的实现类中,利用HashTable存储了Key和Item的键值对。
IMessageItem支持了消息体的嵌套。它包含了两部分:SubValue和SubItem。实现的方式和IMessageItemSequence相似。定义这样的嵌套结构,使得消息的扩展成为可能。一般的结构如下:
IMessage——Name
——ID
——Body(IMessageItemSequence)
——Value
——Item(IMessageItem)
——SubValue
——SubItem(IMessageItem)
——……
各个消息对象之间的关系如下:
在实现服务进程通信之前,我们必须定义好各个服务或各个业务的消息格式。通过消息体的方法在服务的一端设置消息的值,然后发送,并在服务的另一端获得这些值。例如发送消息端定义如下的消息体:
IMessageItem subItem1 = factory.CreateMessageItem(); subItem1.SetSubValue("subsubname11","subsubvalue11"); subItem1.SetSubValue("subsubname12","subsubvalue12"); IMessageItem subItem2 = factory.CreateMessageItem(); subItem1.SetSubValue("subsubname21","subsubvalue21"); subItem1.SetSubValue("subsubname22","subsubvalue22"); item.SetSubItem("subitem1",subItem1); item.SetSubItem("subitem2",subItem2); body.SetItem("item",item); //Send Request Message MyServiceClient service = new MyServiceClient("Client"); IMessageItemSequence reply = service.SendRequest("TestService","Test1",body);
在接收消息端就可以通过获得body的消息体内容,进行相关业务的处理。
二、.Net Remoting服务
在.Net中要实现进程间的通信,主要是应用Remoting技术。根据前面对消息的定义可知,实际上服务的实现,可以认为是对消息的处理。因此,我们可以对服务进行抽象,定义接口IService:
Execute()方法接受一条Request Message,对其进行处理后,返回一条Reply Message。在整个分布式处理架构中,可以认为所有的服务均实现该接口。但受到Remoting技术的限制,如果要实现服务,则该服务类必须继承自MarshalByRefObject,同时必须在服务端被Marshal。随着服务类的增多,必然要在服务两端都要对这些服务的信息进行管理,这加大了系统实现的难度与管理的开销。如果我们从另外一个角度来分析服务的性质,基于消息处理而言,所有服务均是对Request Message的处理。我们完全可以定义一个Request服务负责此消息的处理。
然而,Request服务处理消息的方式虽然一致,但毕竟服务实现的业务,即对消息处理的具体实现,却是不相同的。对我们要实现的服务,可以分为两大类:业务服务与Request服务。实现的过程为:首先,具体的业务服务向Request服务发出Request请求,Request服务侦听到该请求,然后交由其侦听的服务来具体处理。
业务服务均具有发出Request请求的能力,且这些服务均被Request服务所侦听,因此我们可以为业务服务抽象出接口IListenService:
Request服务实现了IService接口,并包含IListenService类型对象的委派,以执行OnRequest()方法:
在RequestListener服务中,继承了MarshalByRefObject类,同时实现了IService接口。通过该类的构造函数,接收IListService对象。
由于Request消息均由Request服务即RequestListener处理,因此,业务服务的类均应包含一个RequestListener的委派,唯一的区别是其服务名不相同。业务服务类实现IListenService接口,但不需要继承MarshalByRefObject,因为被Marshal的是该业务服务内部的RequestListener对象,而非业务服务本身:
Service类是一个抽象类,所有的业务服务均继承自该类。最后的服务架构如下:
我们还需要在Service类中定义发送Request消息的行为,通过它,才能使业务服务被RequestListener所侦听。
string aMessageName,IMessageItemSequence aMessageBody) ...{ IMessage message = m_Factory.CreateMessage(); message.SetMessageName(aMessageName); message.SetMessageID(""); message.SetMessageBody(aMessageBody); IService service = FindService(aServiceName); IMessageItemSequence replyBody = m_Factory.CreateMessageItemSequence(); if (service != null) ...{ IMessage replyMessage = service.Execute(message); replyBody = replyMessage.GetMessageBody(); } else ...{ replyBody.SetValue("result","Failure"); } return replyBody; }
注意SendRequest()方法的定义,其参数包括服务名,消息名和被发送的消息主体。而在实现中最关键的一点是FindService()方法。我们要查找的服务正是与之对应的RequestListener服务。不过,在此之前,我们还需要先将服务Marshal:
this.m_ServiceName +".RequestListener"); }
我们Marshal的对象,是业务服务中的Request服务对象m_RequestListener,这个对象在Service的构造函数中被实例化:
m_RequestListener = new RequestListener(this);
注意,在实例化的时候是将this作为IListenService对象传递给RequestListener。因此,此时被Marshal的服务对象,保留了业务服务本身即Service的指引。可以看出,在Service和RequestListener之间,采用了“双重委派”的机制。
通过调用Initialize()方法,初始化了一个服务对象,其类型为RequestListener(或IService),其服务名为:Service的服务名 + ".RequestListener"。而该服务正是我们在SendRequest()方法中要查找的Service:
IService service = FindService(aServiceName);
下面我们来看看FindService()方法的实现:
可以看到,这个服务是被添加到m_Service对象中,该对象为SortedList类型,服务名为Key,IService对象为Value。如果没有找到,则通过私有方法GetService()来获得:
- · Sun加入OpenAJAX联盟和Dojo基金会
- · 全球十五大最易受攻击软件排名
- · Web2.0渗透商业应用软件 推动员工间协作
- · Web2.0冬天中的暖流 社会化新闻浮出水面
- · 海外安全专家:Web 2.0的技术安全危机
- · Gartner报告称Web 2.0在10年内将影响企业
- · Web2.0时代 网络社区如何为企业创造价值?
- · 精通J2EE应用程序开发之交叉分析J2EE
- · 内存泄漏,走开 轻松搞定Java内存泄漏
- · ASP.NET中动态控制RDLC报表
- · ASP.NET数据库编程快速入门之技术慨述
- · 在ASP.NET应用中插入flash动画
- · ASP.NET中文件上传下载方法集合
- · JavaOne 大会焦点关注 Ajax也疯狂
- · Ruby程序快速入门之简单的例子
- · Eclipse未来:同SOA、Ajax的连接和整合
- · 开源Eclipse风头正劲 Sun态度若明若暗
- · 深入浅出组件编程之组件与控件的区别
- · 组件编程之TypeConverterAttribute
- · Eclipse发布AspectJ 5 正式版
- · MyEclipse4.1 M2发布 支持AJAX
- · 正版软件少人埋单 PC预装模式前景不明
- · Eclipse3.1中体验J2SE5.0之注释类型
- · 用Javap反编译帮你理解Java特性
- · 多处理器平台上J2EE应用的内存争用
- · Java IO 包中的Decorator模式
- · 2005年度Java十大新技术和新产品
- · 2005年Java技术年度综述:融合与开放
- · 品味Eclipse 3.1 中的新特性
- · Eclipse Form程序设计指南之入门
- · 扩展Eclipse辅助和规范开发流程
- · Eclipse3.1中体验J2SE 5.0之枚举类型
- · Google WiFi业务现身网站
- · 利用Eclipse编辑中文资源文件
- · Excel输入分数的六种方法
- · Excel函数应用教程:文本与数据函数
- · JavaOne即将召开 Sun将发布Java EE 5
- · J2EE开发框架发展简史
