netcore grpc

netcore grpc

一、solution

  1. 创建空解决方案
     > dotnet new sln -n Apricot.Grpc
    

二、Grpc.Server

  1. 创建Apricot.Grpc类库项目
     > dotnet new classlib -n Apricot.Grpc
    
     # 解决方案添加类库项目
     > dotnet sln add Apricot.Grpc/Apricot.Grpc.csproj
    
  2. 安装依赖
     > dotnet add package Grpc.AspNetCore --version 2.66.0
     > dotnet add package protobuf-net --version 3.2.30
    
  3. 创建Protos文件夹
    • 添加Garner文件夹,包含增、删、改、查 等操作
    • 添加 garner.proto 文件 [主文件]
      syntax = "proto3";
      option csharp_namespace = "Apricot.Grpc";
      
      package garner;
      
      // google protos
      import "google/protobuf/empty.proto";
      import "google/protobuf/Any.proto";
      
      // garner protos
      import "Protos/Garner/create.proto";
      import "Protos/Garner/update.proto";
      import "Protos/Garner/get.proto";
      import "Protos/Garner/list.proto";
      
      // params protos
      import "Protos/Params/id.proto";
      import "Protos/Params/query.proto";
      
      // results protos
      import "Protos/Results/result.proto";
      
      // services
      service Garner{
          rpc CreateAsync(CreateGarnerRequest) returns(RcpResult);
      
          rpc UpdateAsync(UpdateGarnerRequest) returns(RcpResult);
      
          rpc RemoveAsync(IdParam) returns(RcpResult);
      
          rpc GetAsync(IdParam) returns(GetGarnerResponse);
      
          rpc GetListAsync(QueryParam) returns(GetGarnerListResponse);
      }
      
      
    • 添加 create.proto 文件
      syntax = "proto3";
      
      option csharp_namespace = "Apricot.Grpc";
      
      package garner;
      
      // google empty.proto
      import "google/protobuf/empty.proto";
      
      // create request
      message CreateGarnerRequest{
          string name = 2;
      
          string address = 3;
      }
      
    • 添加 update.proto 文件
      syntax = "proto3";
      
      option csharp_namespace = "Apricot.Grpc";
      
      package garner;
      
      // google empty.proto
      import "google/protobuf/empty.proto";
      
      // update request
      message UpdateGarnerRequest{
          int64 id = 1;
      
          string name = 2;
      
          string address = 3;
      
      }
      
    • 添加 get.proto 文件
      syntax = "proto3";
      
      option csharp_namespace = "Apricot.Grpc";
      
      
      package garner;
      
      // google empty.proto
      import "google/protobuf/empty.proto";
      
      // garner response
      message GetGarnerResponse{
          int32 code = 1;
          string message = 2;
          bool success = 3;
          oneof garner{
              GetGarnerData data =4;
          }
      }
      
      // garner data
      message GetGarnerData{
          int64 id = 1;
      
          string name = 2;
      
          string address = 3;
      
      }
      
      
    • 添加 list.proto 文件
      syntax = "proto3";
      
      option csharp_namespace = "Apricot.Grpc";
      
      package garner;
      
      // google empty.proto
      import "google/protobuf/empty.proto";
      
      // garner list response
      message GetGarnerListResponse{
          int32 code = 1;
          string message = 2;
          bool success = 3;
          int32 total = 4;
          repeated GetGarnerListData rows = 5;
      }
      
      // garner list data
      message GetGarnerListData{
          int64 id = 1;
      
          string name = 2;
      
          string address = 3;
      
      }
      
  4. 项目文件添加 .proto 配置
    <ItemGroup>
      <Protobuf Include="Protos\Results\result.proto" />
      <Protobuf Include="Protos\Params\query.proto" />
      <Protobuf Include="Protos\Params\id.proto" />
      <Protobuf Include="Protos\Garner\get.proto" />
      <Protobuf Include="Protos\Garner\list.proto" />
      <Protobuf Include="Protos\Garner\update.proto" />
      <Protobuf Include="Protos\Garner\create.proto" />
      <Protobuf Include="Protos\Garner\garner.proto" GrpcServices="Server" />
     </ItemGroup>
    
  5. 编译项目
     > dotnet build
    
  6. 查看生成类
     > dir obj\Debug\net8.0\Protos
    
  7. 创建 grpc service
    • 创建 GarnerGrpcService
    • 继承 Garner.GarnerBase
    • 重写方法
    • 整体代码
       public class GarnerGrpcService : Garner.GarnerBase
       {
         public override Task<RcpResult> CreateAsync(CreateGarnerRequest request, ServerCallContext context)
         {
             return Task.FromResult(new RcpResult
             {
                 Code = StatusCodes.Status200OK,
                 Success = true,
             });
         }
      
         public override Task<RcpResult> UpdateAsync(UpdateGarnerRequest request, ServerCallContext context)
         {
             return Task.FromResult(new RcpResult
             {
                 Code = StatusCodes.Status200OK,
                 Success = true,
             });
         }
      
         public override Task<RcpResult> RemoveAsync(IdParam request, ServerCallContext context)
         {
             return Task.FromResult(new RcpResult
             {
                 Code = StatusCodes.Status200OK,
                 Success = true,
             });
         }
      
         public override Task<GetGarnerResponse> GetAsync(IdParam request, ServerCallContext context)
         {
             return Task.FromResult(new GetGarnerResponse
             {
                 Code = StatusCodes.Status200OK,
                 Success = true,
                 Data = new GetGarnerData
                 {
                     Id = Random.Shared.NextInt64(),
                     Address = "127.0.0.1",
                     Name = "garner"
                 }
             });
         }
      
         public override Task<GetGarnerListResponse> GetListAsync(QueryParam request, ServerCallContext context)
         {
             var response = new GetGarnerListResponse
             {
                 Code = StatusCodes.Status200OK,
                 Success = true,
                 Total = 10,
             };
      
             response.Rows.AddRange(new[]
             {
                 new GetGarnerListData
                 {
                     Id = Random.Shared.NextInt64(),
                     Address = "127.0.0.1",
                     Name = "garner"
                 },
                 new GetGarnerListData
                 {
                     Id = Random.Shared.NextInt64(),
                     Address = "127.0.0.1",
                     Name = "apricot"
                 }
             });
      
             return Task.FromResult(response);
         }
      }
      

三、Grpc.WebApi

  1. 创建Apricot.Grpc.WebApi启动项目
     > dotnet new web -n Apricot.Grpc.WebApi
    
     # 解决方案添加启动项目
     > dotnet sln add Apricot.Grpc.WebApi/Apricot.Grpc.WebApi.csproj
    
  2. 添加项目引用
     > dotnet add reference ../Apricot.Grpc/Apricot.Grpc.csproj
    
  3. 注入容器、管道
     // add grpc
     builder.Services.AddGrpc();
    
     // map grpc
     app.MapGrpcService<GarnerGrpcService>();
    
  4. 协议配置
    {
     "Logging": {
         "LogLevel": {
         "Default": "Information",
         "Microsoft.AspNetCore": "Warning"
         }
     },
     "AllowedHosts": "*",
    
     // setting  http2 protocol
     "Kestrel": {
         "EndpointDefaults": {
          "Protocols": "Http2"
         }
     }
    }
    
    • 支持 Http1/Http2 方法
    builder.WebHost.ConfigureKestrel(options =>
     {
         // http2
         options.ListenAnyIP(5132, listenOption =>
         {
             listenOption.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
         });
    
         // http1
         options.ListenAnyIP(5133, listenOption =>
         {
             listenOption.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http1;
         });
     });
    
  5. 启动项目
     > dotnet run
    

四、Grpc.Client

  1. 创建Apricot.Grpc.Client项目
     > dotnet new web -n Apricot.Grpc.Client
    
     # 解决方案添加客户端
     > dotnet sln add Apricot.Grpc.WebApi/Apricot.Grpc.Client.csproj
    
  2. 安装依赖
     > dotnet add package Grpc.Net.Client --version 2.66.0
     > dotnet add package Google.Protobuf --version 3.28.2
     > dotnet add package Grpc.Tools --version 2.67.0
     > dotnet add package Grpc.Net.ClientFactory --version 2.66.0
     > dotnet add package protobuf-net --version 3.2.30
    
  3. 复制 Protos 文件夹至 Apricot.Grpc.Client项目
  4. 添加 .proto 项目配置
     <ItemGroup>
     	<Protobuf Include="Protos\Results\result.proto" />
     	<Protobuf Include="Protos\Params\query.proto" />
     	<Protobuf Include="Protos\Params\id.proto" />
     	<Protobuf Include="Protos\Garner\get.proto" />
     	<Protobuf Include="Protos\Garner\list.proto" />
     	<Protobuf Include="Protos\Garner\update.proto" />
     	<Protobuf Include="Protos\Garner\create.proto" />
     	<Protobuf Include="Protos\Garner\garner.proto" GrpcServices="Client" />
     </ItemGroup>
    
  5. 编译项目
     > dotnet build
    
  6. 注入容器
    // add client
    builder.Services.AddGrpcClient<Garner.GarnerClient>(option =>
     {
         option.Address = new Uri("http://localhost:5132");
     })
    
  7. 服务调用
     app.Map("/grpc", (HttpContext context) =>
     {
    
         var client = context.RequestServices.GetRequiredService<Garner.GarnerClient>();
    
         var data = client.GetListAsync(new QueryParam { PageIdex = 1, PageSize = 10 });
    
         context.Response.WriteAsJsonAsync(data);
    
     });
    

五、apifox 联调 grpc

  1. 个人团队
  2. 新建项目
    • 类型 grpc 项目
  3. 添加 .proto
    • .proto 文件

      • 选择 garner.proto 主文件
    • 依赖关系目录

      • 选择 Protos 文件夹
    • 错误 & 处理

      • 错误:未找到 google protobuf

      • 处理:将 google protobuf 拷贝 Protos 目录

        • 目录:%USERPROFILE%.nuget\packages\grpc.tools\2.66.0\build\native\include\google
      • 错误:未找到 create.proto

      • 处理:将 garner.protoimport 去掉 Protos/ (仅限导入)

    • 导入成功

  4. 接口测试 create、list
    • create
    • list
    • 错误 & 处理
      • 错误:Received RST_STREAM with code 2 triggered by internal client error: Protocol error
      • 处理:将请求地址改成 Http2 协议端口。
posted @ 2024-10-19 17:07  1764564459  阅读(9)  评论(0编辑  收藏  举报