Actor是一种高并发处理模型,每个Actor都有着自己的状态有序消息处理机制,所以在业务处理的情况并不需要制定锁的机制,从而达到更高效的处理能性。XRPC是一个基于远程接口调用的RPC组件,它可以简单地实现高性能的远程接口调用;XRPC在创建远程接口时是支持针对接口创建对应的Actor实例。当创建接口Actor后,所有Client针对这一例实例Actor的所有方法调用都是有序处理。以下介绍如何在XRPC创建并使用Actor

什么场景适用于Actor

既然每个Actor都有着自己的状态和顺序处理机制,那可以针对这优点进行相关业务的展开;在棋牌游戏中的桌子可以是一个Actor,车票里的每一辆车可以是一个Actor,秒杀里的每一种商品是一个Actor。在这些Actor所有的操作都是有序进行,不存在锁,也不需要事务(通过EventSourcing来保障)和不会产生死锁;数据变更全内存操作,通过这样可以大提高业务的处理性能。

引用XRPC

Install-Package BeetleX.XRPC

定义Actor的RPC服务

XRPC支持的Actor服务功能是建立在EventNext之上,它的好处是直接接口行为的Actor创建,而不是传统的消息加接收方法,这样在应用设计和调用上也是非常方便灵活。接下来定义一个简单的Actor服务

  • 接口定义

       public interface IAmountService
    {
    Task<int> Income(int amount);
    Task<int> Payout(int amount);
    Task<int> Get();
    }

    以上是一个简单的帐记变更行为接口

  • 实现接口

       [Service(typeof(IAmountService))]
    public class AmountService : ActorState, IAmountService
    { private int mAmount; public override Task ActorInit(string id)
    {
    return base.ActorInit(id);
    } public Task<int> Get()
    {
    return mAmount.ToTask();
    } public Task<int> Income(int amount)
    {
    mAmount += amount;
    return mAmount.ToTask();
    } public Task<int> Payout(int amount)
    {
    mAmount -= amount;
    return mAmount.ToTask();
    }
    }
  • 启动对应的RPC服务

          private static XRPCServer mXRPCServer;
    
          static void Main(string[] args)
    {
    mXRPCServer = new XRPCServer();
    mXRPCServer.ServerOptions.LogLevel = LogType.Error;
    mXRPCServer.Register(typeof(Program).Assembly);
    mXRPCServer.Open();
    Console.Read();
    }

    以上代码是在默认端口9090上绑定RPC服务,可以通过运行日志查看服务启动情况

创建远程Actor调用

  • 创建RPC Client

     client = new XRPCClient("192.168.2.18", );
    client.Connect();

    以上代码是创建一个RPC客户端,通过它的Create可以创建接口代理

  • 创建接口Actor实例
    IAmountService henry = client.Create<IAmountService>("henry");
    IAmountService ken = client.Create<IAmountService>("ken");

    以上是针对IAmountService创建了两个Actor对象,这两个对象的操作都是相互隔离互不干扰;每个Actor对象中的方法在并发下都是有序执行,并不会产生线程安全问题,所以在不同方法中操作对像的数据成员都不需要锁来保证数据安全性。

测试

为了更好地验证Actor的隔离和并发安全性,简单地并发测试一下

             for (int i = ; i < concurrent; i++)
{
var task = Task.Run(async () =>
{
for (int k = ; k < requests; k++)
{
await henry.Income();
System.Threading.Interlocked.Increment(ref mCount);
}
});
tasks.Add(task);
task = Task.Run(async () =>
{
for (int k = ; k < requests; k++)
{
await henry.Payout();
System.Threading.Interlocked.Increment(ref mCount);
}
});
tasks.Add(task);
task = Task.Run(async () =>
{
for (int k = ; k < requests; k++)
{
await ken.Income();
System.Threading.Interlocked.Increment(ref mCount);
}
});
tasks.Add(task);
task = Task.Run(async () =>
{
for (int k = ; k < requests; k++)
{
await ken.Payout();
System.Threading.Interlocked.Increment(ref mCount);
}
});
tasks.Add(task);
}
await Task.WhenAll(tasks.ToArray());
double useTime = EventCenter.Watch.ElapsedMilliseconds - start;
Console.WriteLine($"Completed count:{mCount}|use time:{useTime}|rps:{(mCount / useTime * 1000d):###.00} |henry:{await henry.Get()},ken:{await ken.Get()}");

两个程序同时在本机跑了一下,在50并发的情况大概是11万RPS

服务中的Actor隔离性

服务是通过名称来实例化接口的不同Actor,同一服务即使多个Client同时对一名称的Actor进行创建服务也可以保证它的唯一性。

完整示例代码

https://github.com/IKende/XRPC/tree/master/Samples/Actors

.Net core使用XRPC创建远程接口的Actor对象的更多相关文章

  1. RMI(远程接口调用)

    1. RMI的原理: RMI系统结构,在客户端和服务器端都有几层结构. 方法调用从客户对象经占位程序(Stub).远程引用层(Remote Reference Layer)和传输层(Transport ...

  2. C#winForm调用WebService的远程接口

    Web Service 的创建简单编码.发布和部署 上一篇详细概述了WebService的创建,编码,发布和部署,那么作为客户端的程序如何访问远程端的WebService 接下来看一下具体步骤:   ...

  3. Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6633311 在上一篇文章中,我 们分析了And ...

  4. Android开发,Eclipse创建aidl接口时,出错

    Android开发中,当我们需要调用远程Service时,我们一般通过远程接口(RMI)来实现的,而Android的RMI需要AIDL(Android Interface Definition Lan ...

  5. .net core 在扩展中使用接口实例之IServiceProvider

    在.net core 2.0中,我们使用的对象实例大多数都是通过构造函数依赖注入进来的,但那是在一般的类中使用. 如果需要在静态/扩展类中使用某些服务类的对象实例,可以使用如下方式: 1.新建一个Se ...

  6. 带SSL证书的httpclient 远程接口工具类

    package com.iups.wx.util; import java.io.IOException; import java.io.UnsupportedEncodingException; i ...

  7. Atitit.远程接口 监控与木马   常用的api 标准化v2 q216

    Atitit.远程接口 监控与木马   常用的api 标准化v2 q216 1. 木马与远程接口 监控的常用的api2 1.1. 文件复制2 1.2. 屏幕定时截图2 1.3. 邮件发送2 1.4.  ...

  8. HttpClient远程接口调用-实名认证

    1.HttpClient远程接口调用 1)用户注册 注册按钮button提交表单时,要return false form表单 <!-- action="http://localhost ...

  9. HttpClient 远程接口调用方式

    远程接口调用方式HttpClient 问题:现在我们已经开发好了接口了,那该如何调用这个接口呢? 答:使用Httpclient客户端.   Httpclient简介 什么是httpclient Htt ...

随机推荐

  1. 电脑当路由使用(目前只在win7上用过)

    前提:电脑有无线网卡,并打开了无线 第一步使用管理员权限运行cmd.exe 1.执行如下命令 netsh wlan set hostednetwork mode=allow ssid=myWifi k ...

  2. paramiko使用1

  3. WPF Visibility属性用法

    WPF Visibility属性用法 Visible 元素在窗体中正常显示 Collaspsed 元素不显示,也不占用空间 Hidden 元素不显示,但是任然为它保留空间

  4. linux日常管理-linux日志

    通过系统日志获得相关信息,出现错误,突发情况可以通过查看日志获得有用的信息.遇到故障,看日志是最常用的方法,在日常工作中一定要养成看日志的习惯. 最核心的日志在这个目录下 日志会无限生成,占用的内存会 ...

  5. Linux下部署MySQL,大小写敏感踩坑记录

    今天在将开发环境中的门户数据库复制到新环境后,使用SqlSugar的ORM框架进行数据库操作的时候,出现了主键找不到的现象.排查了很久终于发现了关键点.特此记录. 1.开发环境:    操作系统:CE ...

  6. 线程中event.wait() event_obj.set() 的使用

    #!/usr/bin/env python import threading # event.wait()##阻断线程向下执行 event_obj.set()#释放进程向下执行 def do(even ...

  7. day18-事务与连接池 6.事务隔离级别与解决问题

    开两个cmd窗口,相当于两个事务. read-uncommitted这种级别是解决不了任何问题的,它什么情况都能出现.刚才演示了脏读,再演示就出现了不可重复读. read-committed隔离级别能 ...

  8. Learning Python 012 函数式编程 1 高阶函数

    Python 函数式编程 1 高阶函数 高阶函数 Q:什么是高阶函数? A:一个函数接收另一个函数作为参数,这种函数就称之为高阶函数. 简单举个例子: def add(x, y, f): return ...

  9. R: 缺失值 & 查看变量类型

    ################################################### 问题:缺失值   18.5.2 有关处理缺失值的各种方法有什么?各自的适用场景. 解决方案: n ...

  10. 引用静态资源的url添加版本号,解决版本发布后的浏览器缓存有关问题

    在日常的工作中,我们经常会遇到页面文件(html,jsp等)中引用的js,css,图片等被修改后,而浏览器依然缓存着老版本的文件,客户一时半会看不到修改后的效果,同时也给生产环境的版本发布带来了一些问 ...