之前通过自己写动态代理和用现成的动态代理库等实现过RPC功能,今天,就写一下如何直接引用GRPC的库来实现业务逻辑。
gRPC的介绍,之前我也说了这个g的含义太多,也包含谷歌的意思了。
可以看这个gRPC的文档介绍 : https://grpc.io/docs/what-is-grpc/
MagicOnion这个库用它是因为它内部使用了 MessagePack-CSharp 序列化方式,这种方式效果要比谷歌的protobuf 效果还要好,更重要的是在Net这个平台下来看的。
MagicOnion 是用于 .NET 平台的现代 RPC 框架,它提供双向实时通信(例如SignalR和Socket.io)以及 RPC 机制(例如 WCF 和基于 Web 的 API)。
该框架基于gRPC,它是一种用于 HTTP/2 的快速且紧凑的二进制网络传输。但是,与普通 gRPC 不同,它将 C# 接口视为协议模式,从而无需.proto(Protocol Buffers IDL)即可在 C# 项目之间实现无缝代码共享。
接口是模式并提供 API 服务,就像普通的 C# 代码一样
其中 MagicOnion开源地址:https://github.com/Cysharp/MagicOnion
实现gRPC业务
我这边结构如下:
客户端,服务端,以及共享接口,三部分组成。
主要引用的Nuget包为:
MagicOnion
MagicOnion.Server
MagicOnion.Client
接口定义
接口定义,是我直接拿之前做的demo的样子直接搞的。也方便。
IDemo.cs
public interface IDemo : IService<IDemo>
{
UnaryResult<string> Say1(string msg);
UnaryResult<int> Say2(string a, int b, List<string> c, Kind kind);
UnaryResult<Kind> Say3(int b, List<string> c, Kind kind);
}
public enum Kind
{
a,
b
}
注
用了这个服务才发现,它不能像我之前自己实现的那样,还能实现Void返回类型和重载函数名等操作。
所以,它只能用于服务类的通讯,不能像函数那样用,另外 UnaryResult 返回类型是必须的,这是需要注意的。
服务端
我这边是直接新建了一个asp.net core web api,注释新增的部分,就是我新增的代码。
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//新增
//增加Grpc
builder.Services.AddGrpc();
builder.Services.AddMagicOnion();
var app = builder.Build();
//新增
app.UseRouting();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
//新增
app.UseEndpoints(endpoints =>
{
endpoints.MapMagicOnionService();
endpoints.MapGet("/", async context =>
{
context.Response.ContentType = "text/plain; charset=utf-8";
await context.Response.WriteAsync("Grpc服务端已经创立,等待Grpc客户端连接!");
});
});
app.Run();
}
Demo接口服务端实现
public class Demo : ServiceBase<IDemo>, IDemo
{
public async UnaryResult<string> Say1(string msg)
{
return msg;
}
public async UnaryResult<int> Say2(string a, int b, List<string> c, Kind kind)
{
return b;
}
public async UnaryResult<Kind> Say3(int b, List<string> c, Kind kind)
{
return kind;
}
}
注
实现接口的同时也要继承eBase类,要不然,总有一些接口的方法未实现。
客户端
客户端就简单许多了
static async Task Main(string[] args)
{
Console.Title = "GrpcDemo by 蓝创精英团队";
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var demo = MagicOnionClient.Create<IDemo>(channel);
Console.WriteLine(await demo.Say1("123"));
Console.WriteLine(await demo.Say2("demo", 6, new List<string>() { "6" }, Kind.b));
Console.WriteLine(await demo.Say3(1, new List<string>(), Kind.a));
Console.WriteLine("不错,完成了任务!");
Console.ReadLine();
}
效果
先运行服务端:
游览器打开地址 : https://localhost:5001/
就可以看到下面的内容,说明服务成功启动!
然后,再运行客户端
结果如下:
用别人的库,确实方便许多。
总结
至此,RPC系列已经完结了,撒花,欧耶!
看着简单,搞着不知不觉已经夜深人静了,山中无岁月,世上已千年啊。
代码地址
https://github.com/kesshei/GrpcDemo.git