• .net6使用gRPC


    一、前言

    gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架。

    gRPC 的主要优点是:

    • 现代高性能轻量级 RPC 框架。
    • 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。
    • 可用于多种语言的工具,以生成强类型服务器和客户端。
    • 支持客户端、服务器和双向流式处理调用。
    • 使用 Protobuf 二进制序列化减少对网络的使用。

    这些优点使 gRPC 适用于:

    • 效率至关重要的轻量级微服务。
    • 需要多种语言用于开发的 Polyglot 系统。
    • 需要处理流式处理请求或响应的点对点实时服务。

    引用自微软官方文档: https://docs.microsoft.com/zh-cn/aspnet/core/grpc/?view=aspnetcore-6.0

    二、创建gRPC服务

    本文使用VS2022+.net6进行演示。

    1、通过模板创建gRPC服务

    2、文件介绍

    greet.proto:协议文件,定义通信的数据结构和服务接口。

    GreeterService:服务类,继承的 Greeter.GreeterBase 是根据proto文件自动生成的

    Startup.cs:将 gRPC服务添加到了终结点路由中

    csproj:项目文件,添加了proto文件引用

    三、创建gRPC客户端并调用

    1、添加名称为GrpcClient的控制台程序

    2、添加Nuget包引用:Grpc.Net.Client、Google.Protobuf、Grpc.Tools

    3、将服务的 proto 文件夹复制到客户端。复制后会自动在工程文件中添加引用,注意将GrpcServices值改为Client

    4、Program.cs中添加客户端调用代码

    var channel = GrpcChannel.ForAddress("https://localhost:5001"); // 服务端地址
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(new HelloRequest { Name = "张三" });
    Console.WriteLine("Greeter 服务返回数据: " + reply.Message);
    Console.ReadKey();
    

    5、运行服务端和客户端,可以看到客户端接受到了服务端返回的数据

    四、创建自己的gRPC服务并调用

    我们以注册登录为例。

    1、在GrpcService > Protos文件夹新建user.proto文件

    定义了注册、登陆、退出、获取所有用户四个方法。

    syntax = "proto3";
    
    option csharp_namespace = "GrpcService";
    
    package user;
    
    // 需要使用空参数和空返回值时,需要使用这个协议文件
    import "google/protobuf/empty.proto"; 
    
    service User {
      // 注册
      rpc Register (UserDTO) returns (CommonResult);
      // 登陆
      rpc Login (LoginDTO) returns (LoginResult);
      // 退出
      rpc Logout (LogoutDTO) returns (CommonResult);
      // 获取所有用户
      rpc GetAllUser (google.protobuf.Empty) returns (AllUser);
    }
    
    message UserDTO {
    	string account = 1;
    	string pwd = 2;
        string name = 3;
        int32 age = 4;
    }
    
    message LoginDTO{
    	string accont = 1;
    	string pwd = 2;
    }
    
    message LoginResult{
    	string token = 1;
    }
    
    message LogoutDTO{
    	string token = 1;
    }
    
    message CommonResult {
    	string code = 1;
        string message = 2;
    }
    
    message AllUser{
    	// repeated 表示集合
    	repeated UserDTO userList = 1; 
    }
    
    
    

    注意:Protobuf支持的类型与C#类型是有差异的,对照关系详见:https://docs.microsoft.com/en-us/aspnet/core/grpc/protobuf?view=aspnetcore-6.0#scalar-value-types

    2、在GrpcService > Services文件夹新建UserService.cs文件

    实现proto中定义的方法

    using Google.Protobuf.WellKnownTypes;
    using Grpc.Core;
    
    namespace GrpcService.Services
    {
        public class UserService : User.UserBase
        {
            private readonly ILogger<UserService> _logger;
            public UserService(ILogger<UserService> logger)
            {
                _logger = logger;
            }
    
            // 存储注册用户
            private static IList<UserDTO> _userDTOs = new List<UserDTO>();
    
            /// <summary>
            /// 注册方法实现
            /// </summary>
            /// <param name="userDTO"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<CommonResult> Register(UserDTO userDTO, ServerCallContext context)
            {
                _userDTOs.Add(userDTO);
                return Task.FromResult(new CommonResult
                {
                    Code = "2000",
                    Message = "注册成功。"
                });
            }
    
            /// <summary>
            /// 登陆方法实现
            /// </summary>
            /// <param name="userDTO"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<LoginResult> Login(LoginDTO userDTO, ServerCallContext context)
            {
                // TODO...
    
                return Task.FromResult(new LoginResult
                {
                    Token = "TestToken"
                });
            }
    
            /// <summary>
            /// 退出方法实现
            /// </summary>
            /// <param name="userDTO"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<CommonResult> Logout(LogoutDTO userDTO, ServerCallContext context)
            {
                // TODO...
    
                return Task.FromResult(new CommonResult
                {
                    Code = "2000",
                    Message = "退出成功。"
                });
            }
    
            /// <summary>
            /// 获取所有用户实现
            /// </summary>
            /// <param name="empty"></param>
            /// <param name="context"></param>
            /// <returns></returns>
            public override Task<AllUser> GetAllUser(Empty empty, ServerCallContext context)
            {
                var allUser = new AllUser();
                allUser.UserList.Add(_userDTOs);
    
                return Task.FromResult(allUser);
            }
        }
    }
    
    

    3、将UserService添加到终结点路由

    4、将GrpcService>Protos>user.proto文件拷贝到GrpcClient>Protos文件夹

    5、在GrpcClient>Program.cs文件加入调用代码

    里面我用到了Newtonsoft.Json做序列化,需要安装Newtonsoft.Json包。

    var channel = GrpcChannel.ForAddress("https://localhost:7145"); // 服务端地址
    var client = new User.UserClient(channel);
    var reply = await client.RegisterAsync(new UserDTO { Account = "zhangsan", Pwd = "123", Name = "张三", Age = 18 });
    Console.WriteLine("User 服务 RegisterAsync 方法返回数据: " + JsonConvert.SerializeObject(reply));
    Console.ReadKey();
    
    var reply1 = await client.RegisterAsync(new UserDTO { Account = "lisi", Pwd = "123", Name = "李四", Age = 20 });
    Console.WriteLine("User 服务 RegisterAsync 返回数据: " + JsonConvert.SerializeObject(reply1));
    Console.ReadKey();
    
    var reply2 = await client.GetAllUserAsync(new Google.Protobuf.WellKnownTypes.Empty());
    Console.WriteLine("User 服务 GetAllUserAsync 返回数据: " + JsonConvert.SerializeObject(reply2));
    Console.ReadKey();
    
    var reply3 = await client.LoginAsync(new LoginDTO() { Accont = "zhangsan", Pwd = "123" });
    Console.WriteLine("User 服务 LoginAsync 返回数据: " + JsonConvert.SerializeObject(reply3));
    Console.ReadKey();
    
    var reply4 = await client.LogoutAsync(new LogoutDTO() { Token = "TestToken" });
    Console.WriteLine("User 服务 LogoutAsync 返回数据: " + JsonConvert.SerializeObject(reply4));
    Console.ReadKey();
    

    至此服务和调用都已完毕,下面开始运行

    6、先运行GrpcService,再运行GrpcClient

    可以看到返回结果正常

    六、总结

    本文列出.net6环境下使用gRPC的简单示例。demo地址:https://github.com/gaozejie/gRPCTest

  • 相关阅读:
    git log
    [转]深入详解javascript之delete操作符
    js性能优化文章集锦
    [转]A记录和CNAME记录的区别
    [转]200 OK (from cache) 与 304 Not Modified------没有这个规则(ETag是否移除)!!!from cache和304,请查看顶部的流程图!
    nodejs渲染到页面的理解
    git之reset
    Mayavi入门
    OpenAcc笔记——update
    Qt笔记——数据库的图形界面
  • 原文地址:https://www.cnblogs.com/gaozejie/p/15876355.html
Copyright © 2020-2023  润新知