.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM