zoukankan      html  css  js  c++  java
  • 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 的配置也仅此而已。来看看测试结果吧:

    演示结果

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

  • 相关阅读:
    缓存IO读写的方式
    mapboxgl 纠偏百度地图
    GIS常用算法
    DevExpress VCL TdxBar工具栏上的按钮等居右对齐无效的问题
    dxRichEditControl、Invalid operation in GDI+ (Code: 2)
    Indy+POP/SMTP收发邮件
    VUE父组件给子组件传对象
    Linux下进程间通信
    Linux下守护进程
    Linux下进程控制相关
  • 原文地址:https://www.cnblogs.com/sofire/p/2222438.html
Copyright © 2011-2022 走看看