您的位置:知识库 » .NET技术

基于消息与.Net Remoting的分布式处理架构

作者: 张逸  来源: 博客园  发布时间: 2010-08-18 11:13  阅读: 2142 次  推荐: 0   原文链接   [收藏]  
摘要:分布式处理在大型企业应用系统中,最大的优势是将负载分布。通过多台服务器处理多个任务,以优化整个系统的处理能力和运行效率。分布式处理的技术核心是完成服务与服务之间、服务端与客户端之间的通信。
[1] 基于消息与.Net Remoting的分布式处理架构
[2] 基于消息与.Net Remoting的分布式处理架构

   三、业务服务对于消息的处理

       前面实现的服务架构,已经较为完整地实现了分布式的服务处理。但目前的实现,并未体现对消息的处理。我认为,对消息的处理,等价与具体的业务处理。这些业务逻辑必然是在服务端完成。每个服务可能会处理单个业务,也可能会处理多个业务。并且,服务与服务之间仍然存在通信,某个服务在处理业务时,可能需要另一个服务的业务行为。也就是说,每一种类的消息,处理的方式均有所不同,而这些消息的唯一标识,则是在SendRequest()方法已经有所体现的aMessageName。

       虽然,处理的消息不同,所需要的服务不同,但是根据我们对消息的定义,我们仍然可以将这些消息处理机制抽象为一个统一的格式;在.Net中,体现这种机制的莫过于委托delegate。我们可以定义这样的一个委托:

public delegate void RequestHandler(string aMessageName,IMessageItemSequence
aMessageBody,
ref IMessageItemSequence aReplyMessageBody);

       在RequestHandler委托中,它代表了这样一族方法:接收三个入参,aMessageName,aMessageBody,aReplyMessageBody,返回值为void。其中,aMessageName代表了消息名,它是消息的唯一标识;aMessageBody是待处理消息的主体,业务所需要的所有数据都存储在aMessageBody对象中。aReplyMessageBody是一个引用对象,它存储了消息处理后的返回结果,通常情况下,我们可以用<"result","Success">或<"result", "Failure">来代表处理的结果是成功还是失败。

       这些委托均在服务初始化时被添加到服务类的SortedList对象中,键值为aMessageName。所以我们可以在抽象类中定义如下方法:     

protected abstract void AddRequestHandlers();
protected void AddRequestHandler(string aMessageName,RequestHandler handler)
{
lock (this.m_EventHandlers)
{
if (!this.m_EventHandlers.Contains(aMessageName))
{
this.m_EventHandlers.Add(aMessageName,handler);
}
}
}
protected RequestHandler FindRequestHandler(string aMessageName)
{
lock (this.m_EventHandlers)
{
RequestHandler handler
= (RequestHandler)m_EventHandlers[aMessageName];
return handler;
}
}

       AddRequestHandler()用于添加委托对象与aMessageName的键值对,而FindRequestHandler()方法用于查找该委托对象。而抽象方法AddRequestHandlers()则留给Service的子类实现,简单的实现如MyService的AddRequestHandlers()方法:

public class MyService:Service
{
public MyService(string aServiceName):base(aServiceName)
{}

protected override void AddRequestHandlers()
{
this.AddRequestHandler("Test1",new RequestHandler(Test1));
this.AddRequestHandler("Test2",new RequestHandler(Test2));
}

private void Test1(string aMessageName,IMessageItemSequence aMessageBody,
ref
IMessageItemSequence aReplyMessageBody)
{
Console.WriteLine(
"MessageName:{0}\n",aMessageName);
Console.WriteLine(
"MessageBody:{0}\n",aMessageBody);
aReplyMessageBody.SetValue(
"result","Success");
}

private void Test2(string aMessageName,IMessageItemSequence aMessageBody,
ref
IMessageItemSequence aReplyMessageBody)
{
Console.WriteLine(
"Test2" + aMessageBody.ToString());
}
}

       Test1和Test2方法均为匹配RequestHandler委托签名的方法,然后在AddRequestHandlers()方法中,通过调用AddRequestHandler()方法将这些方法与MessageName对应起来,添加到m_EventHandlers中。

       需要注意的是,本文为了简要的说明这种处理方式,所以简化了Test1和Test2方法的实现。而在实际开发中,它们才是实现具体业务的重要方法。而利用这种方式,则解除了服务之间依赖的耦合度,我们随时可以为服务添加新的业务逻辑,也可以方便的增加服务。

       通过这样的设计,Service的OnRequest()方法的最终实现如下所示:

public IMessage OnRequest(IMessage aMessage)
{
string messageName = aMessage.GetMessageName();
string messageID = aMessage.GetMessageID();
IMessage message
= m_Factory.CreateMessage();

IMessageItemSequence replyMessage
= m_Factory.CreateMessageItemSequence();
RequestHandler handler
= FindRequestHandler(messageName);
handler(messageName,aMessage.GetMessageBody(),
ref replyMessage);

message.SetMessageName(messageName);
message.SetMessageID(messageID);
message.SetMessageBody(replyMessage);

return message;
}

       利用这种方式,我们可以非常方便的实现服务间通信,以及客户端与服务端间的通信。例如,我们分别在服务端定义MyService(如前所示)和TestService:

public class TestService:Service
{
public TestService(string aServiceName):base(aServiceName)
{}
protected override void AddRequestHandlers()
{
this.AddRequestHandler("Test1",new RequestHandler(Test1));
}
private void Test1(string aMessageName,IMessageItemSequence aMessageBody,
ref
IMessageItemSequence aReplyMessageBody)
{
aReplyMessageBody
= SendRequest("MyService",aMessageName,aMessageBody);
aReplyMessageBody.SetValue(
"result2","Success");
}
}

       注意在TestService中的Test1方法,它并未直接处理消息aMessageBody,而是通过调用SendRequest()方法,将其传递到MyService中。

       对于客户端而言,情况比较特殊。根据前面的分析,我们知道除了发送消息的操作是在客户端完成外,其他的具体执行都在服务端实现。所以诸如MyService和TestService等服务类,只需要部署在服务端即可。而客户端则只需要定义一个实现Service的空类即可:

public class MyServiceClient:Service
{
public MyServiceClient(string aServiceName):base(aServiceName)
{}
protected override void AddRequestHandlers()
{}
}

       MyServiceClient类即为客户端定义的服务类,在AddRequestHandlers()方法中并不需要实现任何代码。如果我们在Service抽象类中,将AddRequestHandlers()方法定义为virtual而非abstract方法,则这段代码在客户端服务中也可以省去。另外,客户端服务类中的aServiceName可以任意赋值,它与服务端的服务名并无实际联系。至于客户端具体会调用哪个服务,则由SendRequest()方法中的aServiceName决定:

IMessageFactory factory = new MessageFactory();
IMessageItemSequence body
= factory.CreateMessageItemSequence();
//……
MyServiceClient service = new MyServiceClient("Client");
IMessageItemSequence reply
= service.SendRequest("TestService","Test1",body);

       对于service.SendRequest()的执行而言,会先调用TestService的Test1方法;然后再通过该方法向MyService发送,最终调用MyService的Test1方法。

       我们还需要另外定义一个类,负责添加服务,并初始化这些服务:

public class Server
{
public Server()
{
m_Services
= new ArrayList();
}
private ArrayList m_Services;
public void AddService(IListenService service)
{
this.m_Services.Add(service);
}
public void Initialize()
{
IDictionary tcpProp
= new Hashtable();
tcpProp[
"name"] = "tcp9090";
tcpProp[
"port"] = 9090;
TcpChannel channel
= new TcpChannel(tcpProp,
new
BinaryClientFormatterSinkProvider(),
new
BinaryServerFormatterSinkProvider());
ChannelServices.RegisterChannel(channel);
foreach (Service service in m_Services)
{
service.Initialize();
}
}
}

       同理,这里的Channel,IP和Port均应通过配置文件读取。最终的类图如下所示:

Distribute3.gif


       在服务端,可以调用Server类来初始化这些服务:      

static void Main(string[] args)
{
MyService service
= new MyService("MyService");
TestService service1
= new TestService("TestService");
Server server
= new Server();
server.AddService(service);
server.AddService(service1);
server.Initialize();
Console.ReadLine();
}

   四、结论

       利用这个基于消息与.Net Remoting技术的分布式架构,可以将企业的业务逻辑转换为对消息的定义和处理。要增加和修改业务,就体现在对消息的修改上。服务间的通信机制则完全交给整个架构来处理。如果我们将每一个委托所实现的业务(或者消息)理解为Contract,则该结构已经具备了SOA的雏形。当然,该架构仅仅处理了消息的传递,而忽略了对底层事件的处理(类似于Corba的Event Service),这个功能我想留待后面实现。

       唯一遗憾的是,我缺乏验证这个架构稳定性和效率的环境。应该说,这个架构是我们在企业项目解决方案中的一个实践。但是解决方案则是利用了CORBA中间件,在Unix环境下实现并运行。本架构仅仅是借鉴了核心的实现思想和设计理念,从而完成的在.Net平台下的移植。由于Unix与Windows Server的区别,其实际的优势还有待验证。

[第1页][第2页]
0
0

.NET技术热门文章

    .NET技术最新文章

      最新新闻

        热门新闻