netcore grpc
一、solution
- 创建空解决方案
> dotnet new sln -n Apricot.Grpc
二、Grpc.Server
- 创建
Apricot.Grpc
类库项目> dotnet new classlib -n Apricot.Grpc # 解决方案添加类库项目 > dotnet sln add Apricot.Grpc/Apricot.Grpc.csproj
- 安装依赖
> dotnet add package Grpc.AspNetCore --version 2.66.0 > dotnet add package protobuf-net --version 3.2.30
- 创建
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; }
- 添加
- 项目文件添加
.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>
- 编译项目
> dotnet build
- 查看生成类
> dir obj\Debug\net8.0\Protos
- 创建
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
- 创建
Apricot.Grpc.WebApi
启动项目> dotnet new web -n Apricot.Grpc.WebApi # 解决方案添加启动项目 > dotnet sln add Apricot.Grpc.WebApi/Apricot.Grpc.WebApi.csproj
- 添加项目引用
> dotnet add reference ../Apricot.Grpc/Apricot.Grpc.csproj
- 注入容器、管道
// add grpc builder.Services.AddGrpc(); // map grpc app.MapGrpcService<GarnerGrpcService>();
- 协议配置
{ "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; }); });
- 支持
- 启动项目
四、apifox 联调 grpc
- 个人团队
- 新建项目
- 类型
grpc
项目
- 类型
- 添加
.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.proto
中import
去掉Protos/
(仅限导入)
-
-
导入成功
-
- 接口测试
create、list
- create
- list
- create