让分布式远程调用优雅些

现在的系统越来越庞大复杂,对系统进行拆分,让各个独立模块各干各的事,已经是现有大型系统普遍采用的解决方案,美其名曰SOA,说的狭窄一点,就是原来是本地调用的,现在变成了远程调用,于是乎,各种远程调用的方案冒出来了,Remoting、WCF、REST等等,这些名词的堆积起来,让开发者有点不知所然,要花很多时间去理解和消化这些概念,而对于真正的业务编码却花不了这么多时间;为何不让这些细节隐藏起来,让远程调用如同本地调用一样方便简单呢?让中间的细节,比如通讯方式是TCP还是HTTP,序列化是SOAP还是JSON,性能效率、负载均衡等等问题,都交给架构师、框架设计师去处理吧,我们只需要关心自己的业务实现就可以,这个愿望很简单吧。

我们设想有这么个服务,我们把它看成是.NET里的接口, 如下代码所示:

1 namespace ClassLibrary1
2 {
3     public interface IClassService
4     {
5         string HelloWorld();
6     }
7 }  

这个接口定义在ClassLibrary1.dll中,我们期望这么去调用:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using ClassLibrary1;
 5 using HTB.DevFx.Esb;
 6 
 7 namespace ConsoleApplication2
 8 {
 9     class Program
10     {
11         static void Main(string[] args) {
12             var svr = ServiceLocator.GetService<IClassService>();
13             Console.WriteLine(svr.HelloWorld());
14             Console.ReadLine();
15         }
16     }
17 }

以上代码定义在ConsoleApplication2.exe中。是不是很简单,我们是调用者,没必要关心谁是接口的实现者,交给IoC好了。至于这返回的svr是远程对象还是本地对象,我们更无需关心了。只管调用好了。

 

当然了,在具体运行时,总该有一个实现者来实现接口吧,但以上代码找不到谁实现了这个接口。我们把实现这个接口的代码定义在CosoleApplication1.exe中,如下:

 1 using System;
 2 using ClassLibrary1;
 3 using HTB.DevFx.Remoting;
 4 
 5 namespace ConsoleApplication1
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args) {
10             RemotingHelper.RemotingServiceInitialize();
11             Console.WriteLine("Ready....");
12             Console.ReadLine();
13         }
14     }
15 
16     internal class ClassServiceInternal : IClassService
17     {
18         public string HelloWorld() {
19             return DateTime.Now.ToString();
20         }
21     }
22 }

 看,我们有一个实现,而且是internal的,这里稍微解释下Main函数里做的事情,就是让ClassServiceInternal以服务的形式发布出去,更具体的留待后文解释。

好了,我们现在有实现者了,那怎么让调用者调用我们的实现者呢,总不能让ConsoleApplication2.exe引用ConsoleApplication1.exe吧,再说了,实现类是internal的,引用了也不能直接调用。既然IClassService都已经按服务的方式发布出去了,我们只需要远程调用就可以啦,让IoC帮我们吧,我们期望我们的IoC配置也需要尽量简单,所以在ConsoleApplication2.exe.config中,我们配置如下:

 1 <?xml version="1.0"?>
 2 <configuration>
 3     <configSections>
 4         <section name="htb.devfx" type="HTB.DevFx.Config.ConfigSectionHandler, HTB.DevFx.BaseFx" />
 5     </configSections>
 6 
 7     <htb.devfx>
 8         <objects configSet="{tag:'object'}">
 9             <object name="ClassServiceClient" type="ClassLibrary1.IClassService, ClassLibrary1" mapTo="http://localhost:8296/classService.rem" builder="@RemotingObjectBuilder" />
10         </objects>
11     </htb.devfx>
12 </configuration>

如上配置,我们期望我们的接口IClassService映射到远程服务接口http://localhost:8296/classService.rem上,这个远程地址是ConsoleApplication1.exe发布出去的。很直观很简单。当然,我们可以把它映射成本地实现,比如本地的Mock实现,这样有利于单元测试和同步开发。

以上均得益于基于配置的IoC框架DevFx,DevFx让我们调用服务如此简单(是不是有广告的嫌疑?) 

具体原理留待后文讲解。

以上代码下载:测试代码 

有关DevFx的更多细节:http://devfx.codeplex.com/ 

 

posted @ 2011-11-10 11:38  R2  阅读(2384)  评论(7编辑  收藏  举报