vRemoting——开源高性能仿Remoting远程交互组件(上)

  1. 组件简介
  2. 服务端演示
  3. 客户端演示
  4. 结束语
  5. 下载地址

·〉组件简介

(下载链接在文章后面)

在企业软件的建设中,不乏碰到点对点连接,从最初的“数据库直连”,到所谓的“三层架构”。用过 WCF,用过 Remoting。都觉得它们不错。毕竟是微软自家的东西,抽象程度很高,配置性很强。但在使用的过程中难免碰到许多问题,无论是连接产生的问题还是配置产生的问题,总是令人烦不胜烦。比如 Remoting,在使用人数比较多的情况下竟然会很慢?WCF是不是发生无法连接。当然,这可能是由于自身并没有研究透这些东西,也没仔细去追究问题的根本。了解Sofire.vRemoting组件,至少可以让您更明白远程交互的原理。

我喜欢研究。两年来琢磨了很多东西,比如 MSIL、WindowsDesigner和WebKit,这三个都是比较偏门的东西。话题扯远了,从性能上来说,我感觉会比 Remoting 和 WCF 快,因为我采用了大量缓存和 MSIL。但也只是凭感觉,实际上我并没有做测试(最新我做了测试,速度比 Remoting 快 1/3,有兴趣的朋友可以试试)。我唯一做的测试是开了一万条线程,连接服务器。因网络饱和,而出现了5次错误。其余的全部测试成功(每个测试2个连接和4-8 个调用)。

整个代码非常精简,注释也完全到位,并且支持配置文件。前后我花了一个礼拜多的时间。犹豫了一下,将 vRemoting 作为 SOFIRE 套件开源的第一季产品

以下是解决方案简图(红框处):

解决方案简图

·〉服务端演示

新建一个项目,【vRemotingTest.Comm】,这是一个公共类库,可用于服务端和客户端。

IService.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace vRemotingTest.Comm
  7. {
  8.     public interface IService
  9.     {
  10.         int Sum(int a, int b);
  11.  
  12.         int Sum(params int[] values);
  13.  
  14.         string ToUpper(string str);
  15.  
  16.         void MakeStringUpperCase(ref string str);
  17.  
  18.         void MakeStringLowerCase(string str, out string lowerCaseString);
  19.  
  20.         void CalculateArea(ref Rectangle rectangle);
  21.  
  22.         void Square(long a, out long b);
  23.  
  24.         string Version1 { get; }
  25.         string Version2 { get; set; }
  26.     }
  27.  
  28.     [Serializable]
  29.     public class Rectangle
  30.     {
  31.         private int _width;
  32.         private int _height;
  33.         private int _area;
  34.  
  35.         public Rectangle(int height, int width)
  36.         {
  37.             _height = height;
  38.             _width = width;
  39.             _area = -1;
  40.         }
  41.  
  42.         public int Area
  43.         {
  44.             get { return _area; }
  45.             set { _area = value; }
  46.         }
  47.  
  48.         public int Height
  49.         {
  50.             get { return _height; }
  51.         }
  52.  
  53.         public int Width
  54.         {
  55.             get { return _width; }
  56.         }
  57.     }
  58. }

从上面的声明来看,服务契约包与普通 Remoting 或 WCF 的契约是一致的。比较引人关注的是,有部分方法包含了 ref 和 out 参数。这也证明了,vRemoting是支持 ref 和 out 参数的。vRemoting 支持:this索引器、属性、方法。可惜不包括事件,远程交互对事件的处理是一件非常麻烦的事情,我有了一点思路,但目前还没找到一个较为完整的方案。所以事件并不支持。但这并不妨碍vRemoting做双向交互。

新建一个项目,【vRemotingTest.Server】,这是测试的服务端。

建立服务契约的实现:

ServiceImpl.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using vRemotingTest.Comm;
  6.  
  7. namespace vRemotingTest.Server
  8. {
  9.     public class ServiceImpl : IService
  10.     {
  11.         #region IService
  12.  
  13.         public int Sum(int a, int b)
  14.         {
  15.             return a + b;
  16.         }
  17.  
  18.         public int Sum(params int[] values)
  19.         {
  20.             int sum = 0;
  21.             foreach(int value in values)
  22.                 sum += value;
  23.             return sum;
  24.         }
  25.  
  26.         public string ToUpper(string str)
  27.         {
  28.             return str.ToUpper();
  29.         }
  30.  
  31.         public void MakeStringUpperCase(ref string str)
  32.         {
  33.             str = str.ToUpper();
  34.         }
  35.  
  36.         public void MakeStringLowerCase(string str, out string lowerCaseString)
  37.         {
  38.             lowerCaseString = str.ToLower();
  39.         }
  40.  
  41.         public void CalculateArea(ref Rectangle rectangle)
  42.         {
  43.             rectangle.Area = rectangle.Width * rectangle.Height;
  44.         }
  45.  
  46.         public void Square(long a, out long b)
  47.         {
  48.             b = a * a;
  49.         }
  50.  
  51.         public string Version1
  52.         {
  53.             get { return "Version1"; }
  54.         }
  55.  
  56.         private string _Version2;
  57.  
  58.         public string Version2
  59.         {
  60.             get
  61.             {
  62.                 return this._Version2;
  63.             }
  64.             set
  65.             {
  66.                 this._Version2 = value;
  67.             }
  68.         }
  69.  
  70.         #endregion
  71.     }
  72. }

紧接着是配置文件【DefaultSetting.xml】:

DefaultSetting.xml
  1. <?xmlversion="1.0"encoding="utf-8" ?>
  2. <ApplicationName=""
  3.              ReturnsError="True">
  4.   <!-- tcp://localhost:8000/One/HelloService.v -->
  5.   <HostName="One"
  6.         ReturnsError="True"
  7.         Port="8000">
  8.       <ServiceName="HelloService"
  9.               ReturnsError="True"
  10.               InstanceMode="Default"
  11.               Contract="vRemotingTest.Comm.IService, vRemotingTest.Comm"
  12.               Type="vRemotingTest.Server.ServiceImpl, vRemotingTest.Server"/>
  13.   </Host>
  14. </Application>

从配置文件可以看出,配置并不复杂。Application 表示一个“服务应用程序”,一个服务应用程序包含 N 个服务主机,每个服务主机包含N个服务

服务端的最后一步(只放出部分代码,其余代码见下载示例):

Program.cs
  1. static void Main(string[] args)
  2. {
  3.     try
  4.     {
  5.         RemotingApplication.Initialization("DefaultSetting.xml");
  6.     }
  7.     catch(Exception e)
  8.     {
  9.  
  10.         Console.WriteLine(e);
  11.         Console.ReadLine();
  12.         return;
  13.     }
  14.     RemotingApplication.ApplicationOpening += new EventHandler(RemotingApplication_ApplicationOpening);
  15.     RemotingApplication.ApplicationOpened += new EventHandler(RemotingApplication_ApplicationOpened);
  16.     RemotingApplication.ApplicationClosing += new EventHandler(RemotingApplication_ApplicationClosing);
  17.     RemotingApplication.ApplicationClosed += new EventHandler(RemotingApplication_ApplicationClosed);
  18.  
  19.     RemotingApplication.ServerOpening += new EventHandler(RemotingApplication_ServerOpening);
  20.     RemotingApplication.ServerOpened += new EventHandler(RemotingApplication_ServerOpened);
  21.     RemotingApplication.ServerFailed += new ExceptionEventHandler(RemotingApplication_ServerFailed);
  22.     RemotingApplication.ServerClosing += new EventHandler(RemotingApplication_ServerClosing);
  23.     RemotingApplication.ServerClosed += new EventHandler(RemotingApplication_ServerClosed);
  24.  
  25.     RemotingApplication.ClientJoined += new EventHandler(RemotingApplication_ClientJoined);
  26.     RemotingApplication.ClientFailed += new ClientFailedEventHandler(RemotingApplication_ClientFailed);
  27.     RemotingApplication.ClientQuitted += new EventHandler(RemotingApplication_ClientQuitted);
  28.     RemotingApplication.Open();
  29.     Console.ReadLine();
  30.     RemotingApplication.Close();
  31. }

好了,至此,服务端顺利完成。

·〉客户端演示

相较于服务端,客户端较为简单,只需要简单几步便可以与契约服务进行交互。

新建一个项目,【vRemotingTest.Client】,代码仅仅如下:

Program.cs
  1. static void Main(string[] args)
  2.         {
  3.             ProxyFactory.Register<IService>("tcp://localhost:8000/One/HelloService.v");
  4.  
  5.             Console.WriteLine("Press enter continue..");
  6.             Console.ReadLine();
  7.  
  8.             IService client = ProxyFactory.Create<IService>();
  9.             Console.WriteLine(client.Sum(2, 3));
  10.             Console.WriteLine(client.Sum(2, 3, 4, 5, 6, 7, 8, 9));
  11.             Console.WriteLine(client.ToUpper("this string used to be lower case"));
  12.             string str = "this was a lower case string";
  13.             client.MakeStringUpperCase(ref str);
  14.             Console.WriteLine(str);
  15.             string lowerCaseString;
  16.             client.MakeStringLowerCase("THIS WAS AN UPPER CASE STRING", out lowerCaseString);
  17.             Console.WriteLine(lowerCaseString);
  18.             Rectangle rect = new Rectangle(30, 40);
  19.             Console.WriteLine(String.Format("Area before call : {0}", rect.Area));
  20.             client.CalculateArea(ref rect);
  21.             Console.WriteLine(String.Format("Area after call : {0}", rect.Area));
  22.  
  23.             long b;
  24.             client.Square(123, out b);
  25.             Console.WriteLine(string.Format("123 squared is {0}", b));
  26.  
  27.             ((IDisposable)client).Dispose();
  28.             Console.WriteLine("...................................");
  29.             Console.WriteLine("Test Completed...");
  30.             Console.ReadLine();
  31.         }

·〉结束语

至此,服务端与客户端的配置完成。整个过程我刻意将代码量增多,在实际使用过程中,关于 vRemoting 的配置也仅此而已。来看看测试结果吧:

演示结果

开源是一种分享,如果有人喜欢,或者希望了解原理篇,请推荐一下:),下载地址

posted @ 2011-10-25 09:19  Treenew Lyn  阅读(4147)  评论(72编辑  收藏  举报