XRPC是基于BeetleX扩展一个远程接口调用组件,它提供基于接口的方式来实现远程服务调用,在应用上非常简便。组件提供.NETCore2.1.NETStandard2.0的client版本,因此即使在winfromwpf也可以使用该组件进行服务调用处理。接下来详细讲解一下XRPC使用,从简单的hello到桌面wpf调用服务、ssl通讯安全和对象注入等功能。

引用组件

组件提供了两个版本BeetleX.XRPC对应.NETCore2.1它同时提供服务和客户端调用功能,BeetleX.XRPC.Clients是对应Standard2.0客户端版本,专门针对桌面应用调用而开发。除了这两个组件外还提供了BeetleX.XRPC.Hosting,这个组件专门为XRPC服务提供以Hosting方式运行的支持,如果你想使用DI那也可以通过这个组件实现。

Hello

很多程序的开始都是以Hello来展示使用,接下来就使用组件构建一个Hello的通讯服务。组件的所有服务都需要通过接口来描述,所以在制定服务前需要用接口来描述一下服务需求:

  1. public interface IHello
  2. {
  3. Task<string> Hello(string name);
  4. }

以上是一个Hello服务接口的定义(接口定义要求是所有方法都必须以Task<T>Task作为返回值)。服务实现

  1. [Service(typeof(IHello))]
  2. public class HelloImpl : IHello
  3. {
  4. public Task<string> Hello(string name)
  5. {
  6. return $"hello {name} {DateTime.Now}".ToTask();
  7. }
  8. }

以上是实现服务细节,接下来通过以下代码启动服务:

  1. static void Main(string[] args)
  2. {
  3. var builder = new HostBuilder()
  4. .ConfigureServices((hostContext, services) =>
  5. {
  6. services.UseXRPC(s =>
  7. {
  8. s.ServerOptions.LogLevel = BeetleX.EventArgs.LogType.Trace;
  9. s.ServerOptions.DefaultListen.Port = ;
  10. s.RPCOptions.ParameterFormater = new JsonPacket();//default messagepack
  11. },
  12. typeof(Program).Assembly);
  13. });
  14. builder.Build().Run();
  15. }

以上是在所有IP.Any上的9090端口提供服务。接下来的工作就是如何调用它,XRPC在使用上设计非常方便,所以在调用上会变得非常简单.

  1. client = new XRPCClient("localhost", );
  2. client.Options.ParameterFormater = new JsonPacket();//default messagepack
  3. hello = client.Create<IHello>();
  4. while (true)
  5. {
  6. Console.Write("Enter you name:");
  7. var name = Console.ReadLine();
  8. var result = await hello.Hello(name);
  9. Console.WriteLine(result);
  10. }

只需要指定XRPCClient对应的服务地址和端口,并创建接口即可调用。XRPCClient和它创建的接口都是线程安全的,因此只需要定义一个即可在并发中使用。

参数编码

组件提供jsonmessagepack作为参数传递的编码,messagepack是默认编码使这种编码序列化对象可以达到非常好的效率,但这种编码需要对类的属性进行标记使用也相对麻烦;如果对效率要求不高不想对类进行属性标记可以设置成Json.如果想实现自己的编码方式可以通过实现以下接口:

  1. public interface IParameterFormater
  2. {
  3. void Encode(Options rpcOption, object data, PipeStream stream);
  4.  
  5. object Decode(Options rpcOption, Type type, ArraySegment<byte> data);
  6. }

创建Actor模式对象

Actor是一种非常高效的业务处理模型,每个实例有着独立线程资源,其行所有为是串行操作,所以它这种线程独立性和无锁机制非常适合高并发业务处理;XPRC支持远程Actor创建,并在服务端维持其独立性,在多客户端同时调用同一Actor行为时服务端会保证其自有的特性运行。

  1. public interface IAmount
  2. {
  3. Task Income(int value);
  4. Task Pay(int value);
  5. Task<int> GetValue();
  6. }

以上是一个简单的数量增加接口,实现的服务如下:

  1. [Service(typeof(IAmount))]
  2. public class AmountImpl : IAmount
  3. {
  4.  
  5. private int mAmount;
  6.  
  7. public Task<int> GetValue()
  8. {
  9. return mAmount.ToTask();
  10. }
  11.  
  12. public Task Income(int value)
  13. {
  14. mAmount -= value;
  15. return Task.CompletedTask;
  16. }
  17.  
  18. public Task Pay(int value)
  19. {
  20. mAmount += value;
  21. return Task.CompletedTask;
  22. }
  23. }

组件在actor应用并没有特殊的要求,主要是客户端在创建的时候告诉服务端需要创建一个指标识的actor实例即可,代码如下:

  1. client = new XRPCClient("localhost", );
  2. client.Options.ParameterFormater = new JsonPacket();//default messagepack
  3. henry = client.Create<IAmount>("henry");
  4. ken = client.Create<IAmount>("ken");

以上是针对IAmount创建两个实例,分别是:henryken.服务端会根据请求的标识在服务端维护各自的actor实例。多客户端同时创建相同名称的actor实例怎办?即是多客户端同时创建同一名称的actor和并发调用,服务端都可保证actor实例的唯一性(实际应用需要涉及到actor的状态,信息持久化等,这些就不在这里讨论;XRPC的这一功能则由https://github.com/IKende/EventNext 提供)。

在WPF中调用

有时候需要在winfromwpf中调用服务,这个时候就需要通过BeetleX.XRPC.Clients来实现调用;它所提供的功能和BeetleX.XRPC内置的客户端功能是一样的。接下来做一个简单的数据查询,不过这个示例为了符合客户端的需求还针对方法添加了JWT验证的功能。

  1. public interface IDataService
  2. {
  3. Task<string> Login(string name, string pwd);
  4.  
  5. Task<List<Employee>> List();
  6. }

以上是一个简单的数据查询接口,里面添加了一个登陆方法.

  1. [Service(typeof(IDataService))]
  2. [TokenFilter]
  3. public class DataServiceImpl : IDataService
  4. {
  5. public Task<List<Employee>> List()
  6. {
  7. return DataHelper.Defalut.Employees.ToTask();
  8. }
  9.  
  10. [SkipActionFilter(typeof(TokenFilter))]
  11. public Task<string> Login(string name, string pwd)
  12. {
  13. string token = null;
  14. if (name == "admin" && pwd == "")
  15. token = JWTHelper.Default.CreateToken(name, "admin");
  16. return token.ToTask();
  17.  
  18. }
  19. }

以上是对应的服务实现,但这个服务多了个TokenFilter属性;这个属性是一个过虑器用于验证请求的,Login方法就移走了这个验证过虑器。接下来看来下这个属性的代码:

  1. public class TokenFilter : ActionFilterAttribute
  2. {
  3. public override bool Executing(EventCenter center, EventActionHandler handler, IEventInput input, IEventOutput output)
  4. {
  5. string token = null;
  6. input.Properties?.TryGetValue("token", out token);
  7. var user = JWTHelper.Default.GetUserInfo(token);
  8. if (user!=null)
  9. {
  10. return base.Executing(center, handler, input, output);
  11. }
  12. else
  13. {
  14. output.EventError = EventError.InnerError;
  15. output.Data = new object[] { "操作错误,无权操作相关资源!" };
  16. return false;
  17. }
  18. }
  19. }

过虑器逻辑比较简单就是获取请求头的token属性是否有效,如果有则通过请求没有则拒绝请求。接下来看一下WPF的使用代码:

  1. private IDataService dataService;
  2.  
  3. private XRPCClient XRPCClient;
  4.  
  5. private void Window_Loaded(object sender, RoutedEventArgs e)
  6. {
  7. XRPCClient = new XRPCClient("localhost", );
  8. XRPCClient.Options.ParameterFormater = new JsonPacket();
  9. dataService = XRPCClient.Create<IDataService>();
  10. }
  11.  
  12. private async void CmdSearch_Click(object sender, RoutedEventArgs e)
  13. {
  14. try
  15. {
  16. var data = await dataService.List();
  17. lstEmployees.ItemsSource = data;
  18. }
  19. catch (Exception e_)
  20. {
  21. MessageBox.Show(e_.Message);
  22. }
  23. }
  24.  
  25. private async void CmdLogin_Click(object sender, RoutedEventArgs e)
  26. {
  27. try
  28. {
  29. var token = await dataService.Login(txtName.Text, txtPwd.Text);
  30. txtToken.Content = token;
  31. ((IHeader)dataService).Header["token"] = token;
  32. }
  33. catch(Exception e_)
  34. {
  35. MessageBox.Show(e_.Message);
  36. }
  37. }

代码其实很简单,在窗体构建的时候创建一个XRPCClient并创建对应的接口实例;在这里这里主要是关心token的传递,因为接口上并没有方法可以这样做;其实所有代理接口都实现了一个IHeader接口,只需要做一个显式的转换并在Header上设置对应名称的值即可.

ssl的支持

安全的通讯在服务交互中是必不可少的,XRPC通过支持ssl来解决这一问题;由于这功能是BeetleX的基础核心,所以组件不需要太过于关注只需要简单配置一下证书即可:

  1.    static void Main(string[] args)
  2. {
  3. var builder = new HostBuilder()
  4. .ConfigureServices((hostContext, services) =>
  5. {
  6. services.UseXRPC(s =>
  7. {
  8. JWTHelper.Init();
  9. s.ServerOptions.LogLevel = BeetleX.EventArgs.LogType.Trace;
  10. s.ServerOptions.DefaultListen.Port = ;
  11. s.ServerOptions.DefaultListen.SSL = true;
  12. s.ServerOptions.DefaultListen.CertificateFile = "test.pfx";
  13. s.ServerOptions.DefaultListen.CertificatePassword = "";
  14. s.RPCOptions.ParameterFormater = new JsonPacket();//default messagepack
  15. },
  16. typeof(Program).Assembly);
  17. });
  18. builder.Build().Run();
  19. }

只要在服务中配置好证书和对应的密码即可,服务在启动的时候会看到具体的情况:

服务启用ssl后,客户端在创建XRPCClient指定sslServiceName即可,代码如下:

  1. XRPCClient = new XRPCClient("localhost", , "test");
  2. XRPCClient.CertificateValidationCallback = (s, certificate, chain, sslPolicyErrors) => true;
  3. XRPCClient.Options.ParameterFormater = new JsonPacket();
  4. dataService = XRPCClient.Create<IDataService>();

当无法确定sslServiceName的时候需要添加CertificateValidationCallback委托自己定义验证返回的结果。

对象注入

由于服务对象的创建是由组件托管的,所以很多时候需要对接口服务添加不同的参数和属性方便功能集成。用户可以通过以下事件来服务类创建:

  1.     XRPCServer.EventCenter.ServiceInstance

其实组件提供了BeetleX.XRPC.Hosting扩展来成这功能,通过这个扩展在服务启动时进行注册,代码如下:

  1. var builder = new HostBuilder()
  2. .ConfigureServices((hostContext, services) =>
  3. {
  4. services.AddSingleton(new User { Name = "BeetleX" });
  5. services.UseXRPC(s =>
  6. {
  7. //...
  8. },
  9. typeof(Program).Assembly);
  10. });
  11. builder.Build().Run();

通过services可以给DI容器添注入需要的对象,当容器注册后就可以在服务类的构建函数中定义需要的参数:

  1. [Service(typeof(IHello))]
  2. public class HelloImpl : IHello
  3. {
  4. public HelloImpl(BeetleX.XRPC.XRPCServer server, User user)
  5. {
  6. mServer = server;
  7. mUser = user;
  8. }
  9. }

以上讲述了XRPC的使用情况,详细代码可以访问 https://github.com/IKende/BeetleX-Samples

BeetleX之XRPC使用详解的更多相关文章

  1. BeetleX之HttpClusterApi应用详解

    之前的文章已经介绍过如何使用HttpClusterApi进行去中心化的HTTP集群服务访问,这一章主要详细讲述如何使用HttpClusterApi,主要包括如何定义节点,创建服务接口和使用接口描述不同 ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. 云原生生态周报 Vol. 8 | Gartner 发布云原生趋势

    业界要闻 Gartner 发布云原生基础设施未来的八大趋势:权威分析机构 Gartner 在对 2020 年技术趋势的展望当中指出:“预计2020年所有领先的容器管理软件均内置服务融合技术,到2022 ...

  2. Streamy障碍二:超大排序合并

  3. [***]HZOJ 哪一天她能重回我身边

    %%%神仙题. 居然是图论,我还一直以为是二分图或者啥数据结构. 直接说正解了,将数看作节点,牌看做边,从牌的正面的数想反面连边权为1的边,反面向正面连边权为0的边(注意用到成对存储的技巧,之后会非常 ...

  4. UISearchDisplayController “No Results“ cancel修改

    Recently I needed to fully customize a UISearchBar, so here are some basic "recipes" on ho ...

  5. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  6. 使用git和sourcetree提交代码的一些问题

    今天遇到的几个坑算是解决了1.开始不能用指令提交,可以执行git add命令前添加gitdir=$(git rev-parse --git-dir); scp -p -P 29418 wangtao1 ...

  7. redis 清除缓存

  8. 在 Windows Azure 中运行SuperSocket

    关键字: Windows Azure, WorkRole, InputEndPoint, 云计算, 微软云 什么是 Windows Azure? Windows Azure 是微软的云计算平台!微软的 ...

  9. css实现简单的页面自适应宽度

    1.css样式.lgn{ width:500px; height:20px;}.item_left_yd{ float: left; display: inline-block; width:240p ...

  10. CSS3 ,fill-available、max-content、min-content、fit-content,自适应

    自适应: 撑满空闲空间与收缩到内容尺寸. CSS3将这两种情况分别定义为'fill-availabel'和'fit-content'. 除此之外 ,还新增了更细粒度的'min-content'和'ma ...