一、什么是RPC
RPC是“远程调用(Remote Procedure Call)”的一个名称的缩写,并不是任何规范化的协议,也不是大众都认知的协议标准,我们更多时候使用时都是创建的自定义化(例如Socket,Netty)的消息方式进行调用,相比http协议,我们省掉了不少http中无用的消息内容。因此很多系统内部调用仍然采用自定义化的RPC调用模式进行通信,毕竟速度和性能是内网的关键指标之一,而标准化和语义无关性在外网中举足轻重。所以,为何API网关无法工作在RPC上,因为它没有一个像HTTP/HTTPS那样的通用标准。
二、CzarRpc简介
CzarRpc是作者基于Dotnetty实现的RPC通讯框架,参考了Surging
和Tars.Net
优秀设计,目前正在内部使用中,下面就CzarRpc调用方式做一个简单介绍,测试结构如下:
1、服务接口
新建一个Czar.Rpc.Common
类库,首先需要引用Czar.Rpc
Nuget包。
Install-Package Czar.Rpc
然后定义测试接口IHelloRpc.cs
,也是目前支持的调用方式。
using Czar.Rpc.Attributes;
using Czar.Rpc.Exceptions;
using Czar.Rpc.Metadata;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Czar.Rpc.Common
{
/// <summary>
/// 测试Rpc实体
/// </summary>
[BusinessExceptionInterceptor]
[CzarRpc("Demo.Rpc.Hello")]
public interface IHelloRpc: IRpcBaseService
{
string Hello(int no, string name);
void HelloHolder(int no, out string name);
Task<string> HelloTask(int no, string name);
ValueTask<string> HelloValueTask(int no, string name);
[CzarOneway]
void HelloOneway(int no, string name);
Task TestBusinessExceptionInterceptor();
DemoModel HelloModel(int D1, string D2, DateTime D3);
Task<DemoModel> HelloModelAsync(int D1, string D2, DateTime D3);
DemoModel HelloSendModel(DemoModel model);
DemoModel HelloSendModelParm(string name,DemoModel model);
List<DemoModel> HelloSendModelList(List<DemoModel> model);
}
public class DemoModel
{
/// <summary>
/// 测试1
/// </summary>
public int T1 { get; set; }
/// <summary>
/// 测试2
/// </summary>
public string T2 { get; set; }
/// <summary>
/// 测试3
/// </summary>
public DateTime T3 { get; set; }
public ChildModel Child { get; set; }
}
public class ChildModel
{
public string C1 { get; set; }
}
}
2.服务端
新建一个控制台程序Czar.Rpc.Server
,然后实现服务接口,因为都是测试数据,所以就随意实现了方法。
HelloRpcServer.cs
using Czar.Rpc.Exceptions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Net;
using Czar.Rpc.Common;
namespace Demo.Rpc.Server
{
public class HelloRpcServer: IHelloRpc
{
public EndPoint CzarEndPoint { get; set; }
public string Hello(int no, string name)
{
string result = $"{no}: Hi, {name}";
Console.WriteLine(result);
return result + " callback";
}
public void HelloHolder(int no, out string name)
{
name = no.ToString() + " out";
}
public void HelloOneway(int no, string name)
{
/*
耗时操作
*/
Console.WriteLine($"From oneway - {no}: Hi, {name}");
}
public Task<string> HelloTask(int no, string name)
{
return Task.FromResult(Hello(no, name));
}
public ValueTask<string> HelloValueTask(int no, string name)
{
return new ValueTask<string>(Hello(no, name));
}
public Task TestBusinessExceptionInterceptor()
{
throw new BusinessException()
{
CzarCode = "1",
CzarMessage = "test"
};
}
public DemoModel HelloModel(int D1, string D2, DateTime D3)
{
return new DemoModel()
{
T1 = D1 + 1,
T2 = D2 + "2",
T3 = D3.AddDays(1)
};
}
public async Task<DemoModel> HelloModelAsync(int D1, string D2, DateTime D3)
{
return await Task.FromResult(
ne