Skip to content

SimCivil.Rpc 说明

Chengzhi Tan edited this page Apr 20, 2018 · 6 revisions

简介

SimCivil使用RPC(Remote Procedure Call)处理服务端和客户端以及(将来)分布式服务间的通信。由于目前.net core平台上没有很好的RPC框架,因此造轮子自己实现一个。

SimCivil.Rpc使用Azure/DotNetty作为底层网络框架,利用castle.DynamicProxy 动态生成代理对象,以IoC(Autofac)的方式管理远程服务。

参考用法

服务端

首先对于要实现的服务,需要有一个接口使得服务端和客户端能够对应

    public interface ITestServiceA
    {
        string GetName();
        string HelloWorld(string name);
        int NotImplementedFuc(int i);
        string GetSession(string key);
    }

目前只支持不带有泛型、委托等特性的普通方法,不支持属性、事件、字段等成员。可以支持带有Task返回的异步方法。

然后再根据接口实现服务端的具体执行类

    public class TestServiceA : ITestServiceA
    {
        public IRpcSession Session { get; }
        public string Name { get; set; }

        public TestServiceA(IRpcSession session)
        {
            Session = session;
        }

        public string GetName()
        {
            return Name;
        }

        public string HelloWorld(string name)
        {
            Name = name;

            return $"Hello {name}!";
        }

        public int NotImplementedFuc(int i)
        {
            throw new NotImplementedException();
        }

        public string GetSession(string key)
        {
            return Session[key].ToString();
        }
    }

其中IRpcSession包含了当前会话的持久化信息,可以在不同服务间共享(目前只有LocalRpcSession只能在单个服务端内共享)。IRpcSession可以在构造函数通过注入获取,当客户端断开服务群时销毁。

注意服务中所有触发的异常都可以被自动转发到客户端,之后会设计一种机制选择性的返回异常信息。

随后配置Rpc服务端容器,设定要暴露的服务

var builder = new ContainerBuilder();
builder.UseRpcSession();
builder.RegisterRpcProvider<TestServiceA, ITestServiceA>().InstancePerChannel();

var server = new RpcServer(builder.Build());
server.Bind(9999).Run().Wait();

builder.UseRpcSession()启用会话功能。除了通过调用builder.RegisterRpcProvider<TestServiceA, ITestServiceA>()在构造容器时暴露服务,还可以在正常注册容器服务后调用server.Expose<ITestServiceA>()实现。

### 客户端
客户端也需要服务的接口`ITestServiceA`。
```csharp
using (RpcClient client = new RpcClient())
{
     client.Bind(9999).ConnectAsync().Wait();

     var name = "test";

     var service = client.Import<ITestServiceA>();

     Assert.Equal(service.HelloWorld(name), $"Hello {name}!");
     Assert.Equal(service.GetName(), name);
}
```
配置方法与服务端相似,随后通过`Import`方法获取代理类。接下来的用法就与调用本地方法一样了。
Clone this wiki locally