Git Product home page Git Product logo

netx's Introduction

NetX

一款使用ZYSOCKET-V实现的 Actor+RPC 服务,使用它你可以随随便便做出高性能服务器,以及彻底解决各种锁的问题

使用方式: NUGET方式:

NetX服务器: Install-Package NetxServer
NetX客户端: Install-Package NetxClient
NetX客户端(手机版可用于IOS): Install-Package NetxClient-Portable
NetX代理网关:暂未开发
NetX共享ActorService:暂未开发
NETXActor(ACTOR本机运行版) : Install-Package NetxActor

源代码:github src

RUST版:github src

NetX架构图解: (举例2个例子,不包括其他的奇思妙想) NetX原理结构图 OR

NetX原理结构图2

通过此框架我们可以轻松的构建 如图这样的服务网络,他的性能非常好的,大概比Orleans性能高出5倍以上,内存只需要orleans5分之一.功能强大,Actor,RPC,Event Sourcing,Wake up to sleep,负载均衡,服务路由,服务器主动调用客户端...等等功能.可实现Orleans无法实现的功能.

下面逐步介绍各个功能模块:

NetXServer:

NetXServer结构图: NetXServer结构图

在Server 中 我们一共有2种控制器,一种是RPC控制器,一种是ACTOR控制器.

RPC控制器: 可以定制每个链接的服务.他们是每个链接一个控制器.各个链接他们的RPC控制器是独立的.对于当前连接来说每个RPC控制器的功能是线程安全的. 但是,如果多个RPC控制室他们之间共享的数据,例如数据集合,它们线程是不安全的.如果要全局线程安全的话,所以我们这里需要一个ACTOR控制器.RPC控制器可以直接调用Actor控制器,或者直接调用Client定义的功能函数.

ACTOR控制器: 此控制器是全局线程安全的,每个ACTOR控制器都被一个叫ActorRun的Actor管理类所管理着,他们是实例全局唯一的.Actor容器中含有各种功能,例如 沉睡,唤醒,事件存储等. 他可以被RPC控制器,其他的Actor控制器,或者客户端直接调用.

这2种控制器都是通过TAG 管理服务的.所谓的TAG就是一个int类型的标签.它用来表示所有的开发性功能函数.TAG全局唯一的.甚至这2种控制器都不能重复定义. 因为使用了TAG.所以我们的Actor他们没有继承关系,每个ACTOR都是独立运行的.所以没有ACTOR功能路由,因为不需要,我们只需要通过 TAG就可以直接 一对一的功能调用.

所有的功能模块都定义在DependencyInjection中.在控制器编写时它非常像 Asp.net Core 写一个控制器.我们可以随时从DependencyInjection拿取一个组件.

最后他们是通过ZYSOCKET-V 也就是我第5代SOCKET框架通讯的.从而保障了服务器的性能.

DEMO里面的例子启动一个服务器:

        var server = new NetxServBuilder()
             .ConfigBase(p =>
             {
                 p.ServiceName = "MessageService"; //服务名
                 p.VerifyKey = "123123";  //密码
                 p.ClearSessionTime = 60000; //Session清理时间
             })
              .ConfigSSL(p =>  //配置SSL加密
              {
                  p.Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(
                      $"{new System.IO.DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent}/server.pfx",
                      "testPassword");
                  p.IsUse = true;
              })
              .ConfigureLogSet(p=> //设置日记
              {
                  p.AddConsole();
                  p.AddFilter("Microsoft.EntityFrameworkCore", LogLevel.Error); //过滤EF日记
              })
             .ConfigNetWork(p =>
             {
                // p.Host = "any";  //监听所有IP
                 p.Port = 3000; //服务端口
             })
             .RegisterService(Assembly.GetExecutingAssembly()) //加载当前DLL里面的所有控制器
             .RegisterDescriptors(p=>p.AddSingleton<UserManager, UserManager>()) //添加用户管理器
             .RegisterDescriptors(p=>p.AddDbContext<UserDatabaseContext>(option=> //设置SQL
             {
                 option.UseSqlite("Data Source=UserDatabase.db3");

             }))
             .Build();

       server.Start(); //启动服务

我们可以定义 一组Actor控制器以及一组RPC控制器,它们的定义方式为:

DEMO里面RPC控制器的例子:

  public class UserAsyncController : AsyncController, IServer
   {
     .
     .
             public UserAsyncController(ILogger<UserAsyncController> logger, UserManager userManager)
              {
                    Log = new DefaultLog(logger);
                    this.UserLines = userManager;
              }
   
    .
    .
    .
   }

这里需要注意我们把所有提供的服务写在了IServer中

[Build]
public interface IServer
{

    [TAG(5002)]
    Task<(bool, string)> LogOn(string username, string password);

    [TAG(5003)]
    Task<(bool, User)> CheckLogIn();

    [TAG(5004)]
    Task<List<User>> GetUsers();

    [TAG(5005)]
    Task<(bool, string)> Say(long userId, string msg);

    [TAG(5006)]
    Task<List<LeavingMsg>> GetLeavingMessage();

}

我们的控制器需要实现此接口的功能,实现完成后,客户端只要拿到此IServer接口,就可以直接调用服务器的功能模块了.

关于DEMO中Actor控制器的定义:

[ActorOption(1000,10000)] //这里最大列队为1000,如果10秒没有任务将进入沉睡
public class UserActorController : ActorController, IActorService
{
    public ILog Log { get; }

    public UserDatabaseContext UserDatabase { get; }

    public UserActorController(ILogger<UserActorController> logger,UserDatabaseContext userDatabaseContext)
    {         
        Log = new DefaultLog(logger);
        UserDatabase = userDatabaseContext;
        UserDatabase.Database.EnsureCreated();
    }
    /// <summary>
    /// 沉睡的时候保存数据
    /// </summary>
    /// <returns></returns>
    public async override Task Sleeping()
    {
        if (UserDatabase.ChangeTracker.HasChanges())
        {
            var i = await UserDatabase.SaveChangesAsync();

            if (i > 0)
                Log.Info($"save {i} row data");
        }
    }

同样我们这里需要继承IActorService,这样的话 我们的RPC,CLIENT或者其他的ACTOR就可以通过IActorService 来调用此控制器中的功能了.

详情请看DEMO Chat Room

其他详细的功能演示,我陆续会更新

关于NetXClient:

NetXClient结构图: NetXClient结构图

我们可以通过NetXClient调用 Server的RPC服务,ACTOR服务,以及提供服务给服务器调用. NetXClient提供给服务器调用的服务是线程安全的.

关于设置一个NetXClient例子:

var icontainer = new NetxSClientBuilder()
                .ConfigureLogSet(p =>
                {
                    p.AddDebug().SetMinimumLevel(LogLevel.Trace); //添加DEBUG日记输出
                })
                .ConfigSSL(p => //设置SSL加密
                {
                    p.Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(
                        $"{System.Windows.Forms.Application.StartupPath}/client.pfx"
                        , "testPassword");
                    p.IsUse = true;
                })
                .ConfigSessionStore(() => new Netx.Client.Session.SessionFile()) //如何保存Session需要下次打开 不用登陆
                .ConfigConnection(p => //配置连接
                {
                    p.Host = "127.0.0.1"; //IP
                    p.Port = 3000;  //端口
                    p.ServiceName = "MessageService"; //服务名称
                    p.VerifyKey = "123123"; //密码
                });

   var Client= icontainer.Build(); //生成一个CLIENT

还记得上面的IServer吗?

调用服务器是需要通过TAG的,至于你CLIENT的IServer不一定要和服务器一致,我们甚至可以换个名字,或者把IActorServer和IServer2个接口的功能整合在一起. 但要注意的是TAG和 参数必须和服务器提供的一致哦

关于服务的调用方式图解: 关于服务的调用方式图解

我们通过IServer调用服务器:

var service = Client.Get<IServer>();
var (success, msg) = await service.LogOn("username", "password");

对就是那么简单.通用的方式一样用于调用Actor服务 如果提供可以服务给服务器调用呢?

  public partial class WinMain : Form, IMethodController, IClient
  {
    public INetxSClient Current { get=>Dependency.Client; set { } }

例如我们这个WINFROM 窗口类需要提供给服务器直接调用.我们首先要继承IMethodController接口,实现 public INetxSClient Current { get=>Dependency.Client; set { } } 因为每次服务器调用此类服务的时候会设置Current,所以{get;set;}即可,但是ChaT Room Client Demo里面的这个Current有特殊的需要,所以我们就这样写吧. IClient 定义了我们提供哪些方法供服务器直接调用. 例如我们搞个方法,给服务器设置用户的状态,用于显示:

 public void SetUserStats(long userid, byte status)
    {
        this.BeginInvoke(new EventHandler((a, b) =>
        {

            foreach (ListViewItem item in this.listView1.Items)
            {
                if (item.Tag is User user)
                {
                    if (user.UserId == userid)
                    {
                        user.OnLineStatus = status;
                        item.SubItems[1].Text = user.OnLineStatus == 0 ? "Offline" : user.OnLineStatus == 2 ? "Leave" : "Online";
                    }
                }
            }
        }));
    }

详情我们可以查看 ClientDemo

关于NETXClient-Portable: 一款用于手机的客户端组件,可以完美的运行于安卓和IOS系统. 我特地提供了DEMO

IOS 实体机 测试: IOS DEMO

NetX代理网关和NetX共享ActorService 我还没有时间开发,但是通过Server和CLIENT我们已经可以实现很多功能了! 下面是 网关图解: NetXProxy

NETXActor: 我提供了一个 ActorRun 本机版,你可以单独拿出来使用就像 AKKA.NET. 他的性能是AKKA.NET本机运行的3倍以上,达到了3M TPS, 也就是1秒钟可以处理300W个事务.

关于使用方式: 我看可以参考集成测试: Actor集成测试

最后我朋友看我最近在做ACTOR框架,所以他也尝试了写了一个. 据说本机性能高出了AKKA.NET 一截. 所以我把他的DEMO拿来了,添加了我的NETXActor Src:AKKA.NET VS event next VS NetX

下面是结果图: AKKA.NET VS event next VS NetX:

*在并行的情况下基本上都是能达到4M TPS的,如果是单线程测试避免了线程调度开销 也就是ActorTest里面的例子,可以达到3.2M TPS

netx's People

Contributors

luyikk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

netx's Issues

Fody: An unhandled exception occurred:

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 Fody: An unhandled exception occurred:
Exception:
请求的操作无法在使用用户映射区域打开的文件上执行。

Type:
System.IO.IOException
StackTrace:
在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
在 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
在 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
在 Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters) 位置 C:\Code\Fody\cecil\Mono.Cecil\ModuleDefinition.cs:行号 1143
在 InnerWeaver.WriteModule() 位置 C:\projects\fody\FodyIsolated\ModuleWriter.cs:行号 18
在 InnerWeaver.Execute() 位置 C:\projects\fody\FodyIsolated\InnerWeaver.cs:行号 113
Source:
mscorlib
TargetSite:
Void WinIOError(Int32, System.String) TCS

Fody: An unhandled exception occurred

每新建一个项目第二次生成的时候都会提示 Fody: An unhandled exception occurred
详细信息
Exception:
Member 'System.Threading.Tasks.Task1<System.Collections.Generic.IEnumerable1<UserService.Abstractions.DTOs.UserInfo>> UserService.Abstractions.IUserService::GetUsers(UserService.Abstractions.QueryOption.UserQueryOption)' is declared in another module and needs to be imported
Type:
System.ArgumentException
StackTrace:
在 Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 2228
在 Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction) 位置 C:\Code\Fody\cecil\Mono.Cecil.Cil\CodeWriter.cs:行号 270
在 Mono.Cecil.Cil.CodeWriter.WriteInstructions() 位置 C:\Code\Fody\cecil\Mono.Cecil.Cil\CodeWriter.cs:行号 180
在 Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition method) 位置 C:\Code\Fody\cecil\Mono.Cecil.Cil\CodeWriter.cs:行号 118
在 Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method) 位置 C:\Code\Fody\cecil\Mono.Cecil.Cil\CodeWriter.cs:行号 54
在 Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 1643
在 Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 1635
在 Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 1433
在 Mono.Cecil.MetadataBuilder.AddTypes() 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 1405
在 Mono.Cecil.MetadataBuilder.BuildTypes() 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 1259
在 Mono.Cecil.MetadataBuilder.BuildModule() 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 1029
在 Mono.Cecil.MetadataBuilder.BuildMetadata() 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 999
在 Mono.Cecil.ModuleWriter.<>c.b__2_0(MetadataBuilder builder, MetadataReader _) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 137
在 Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func3 read) 位置 C:\Code\Fody\cecil\Mono.Cecil\ModuleDefinition.cs:行号 930 在 Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 136 在 Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable1 stream, WriterParameters parameters) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 115
在 Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters) 位置 C:\Code\Fody\cecil\Mono.Cecil\AssemblyWriter.cs:行号 77
在 Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters) 位置 C:\Code\Fody\cecil\Mono.Cecil\ModuleDefinition.cs:行号 1119
在 InnerWeaver.WriteModule() 位置 C:\projects\fody\FodyIsolated\ModuleWriter.cs:行号 21
在 InnerWeaver.Execute() 位置 C:\projects\fody\FodyIsolated\InnerWeaver.cs:行号 112
Source:
Mono.Cecil
TargetSite:
Mono.Cecil.MetadataToken LookupToken(Mono.Cecil.IMetadataTokenProvider)
UserService 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.