NETCORE - Grpc 通信
NETCORE - Grpc 通信
项目框架:Net6
一. 服务端项目
1. 创建 ASP.NET Core gRPC 框架项目:NETCORE.GrpcService
安装插件包
Grpc.AspNetCore.Server.Reflection
Grpc.Tools
2. 注意 appsettings.json 文件中的配置,(webapi中不能这么配置,需开启http2 )
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "Kestrel": { "EndpointDefaults": { "Protocols": "Http2" } } }
3. 在Protos下增加新的 文件 sence.proto
syntax = "proto3"; option csharp_namespace = "RailAssist.Grpc"; import "google/protobuf/wrappers.proto"; package sence; // The greeting service definition. service senceInfoer { // Sends a greeting rpc GetSenceInfo (SenceInfoRequest) returns (SenceInfoReply); } // The request message containing the user's name. message SenceInfoRequest { int32 fileId = 1; //repeated string arr= 2;//list<string>类型 } message NodeInfo { int64 Id = 1; google.protobuf.StringValue Name= 2; google.protobuf.Int64Value ParentId = 3; } message PropSetInfo { int64 Id = 1; google.protobuf.StringValue Name= 2; int64 nodeId=3; } message PropInfo { int64 Id = 1; google.protobuf.StringValue Name= 2; google.protobuf.StringValue Type=3; google.protobuf.StringValue Value=4; google.protobuf.StringValue Unit=5; int64 PsetId=6; } // The response message containing the greetings. message SenceInfoReply { repeated NodeInfo nodeArr = 1; repeated PropSetInfo propSetArr = 2; repeated PropInfo propArr = 3; }
4. 在Services 下 增加新的服务 SenceService.cs
using Grpc.Core; using Rail.Service.TestPlatform.IService; using RailAssist.Grpc; namespace RailAssist.Grpc.Services; public class SenceService : senceInfoer.senceInfoerBase { private readonly ILogger<SenceService> _logger; private ISencesRepository iSencesRepository; public SenceService(ILogger<SenceService> logger, ISencesRepository _iSencesRepository) { _logger = logger; iSencesRepository = _iSencesRepository; } public override async Task<SenceInfoReply> GetSenceInfo(SenceInfoRequest request, ServerCallContext context) { //// 创建 NodeInfo 对象的列表 //var nodeInfoList = new List<NodeInfo> //{ // new NodeInfo { Id = 1, Name = "NodeA" }, // new NodeInfo { Id = 2, Name = "NodeB" }, // // ... 添加更多 NodeInfo 对象 ... //}; //// 创建 SenceInfoReply 实例并设置 node_info_arr 字段 //var reply = new SenceInfoReply //{ // NodeArr = { nodeInfoList } // 使用集合初始化器添加元素到 repeated 字段 //}; //// 返回 Task,因为 gRPC 方法是异步的 //return Task.FromResult(reply); var resData = await iSencesRepository.GetSenceInfo(request.FileId); var nodeInfoList = from n in resData.nodeArr select new NodeInfo { Id = n.Id, Name = n.Name, ParentId = n.ParentId }; var propSetInfoList = from n in resData.propSetArr select new PropSetInfo { Id = n.Id, Name = n.Name, NodeId = n.nodeId }; var propInfoList = from n in resData.propArr select new PropInfo { Id = n.Id, Name = n.Name, PsetId = n.PsetId, Type = n.Type, Unit = n.Unit, Value = n.Value }; var reply = new SenceInfoReply { NodeArr = { nodeInfoList }, PropSetArr = { propSetInfoList }, PropArr = { propInfoList } }; //return Task.FromResult(reply); return reply; } }
5. 在Program.cs 中注入服务
app.MapGrpcService<SenceService>();
6. 注意数据量大小限制的配置,在Program.cs 中
builder.Services.AddGrpc(options => { options.MaxReceiveMessageSize = int.MaxValue; // 设置接收消息的最大尺寸 options.MaxSendMessageSize = int.MaxValue;// 来限制发送消息的最大尺寸 });
6. 项目启动后地址:https://localhost:7180
二. Postman测试
上传
三. 发布项目 - 本地
发布项目后,不可用IIS,不支持。
可在发布文件夹内,双击.exe文件启动。
或执行命令:
dotnet GrpcTempServer.dll cc --urls "http://0.0.0.0:5000"
四. 发布项目 - Docker
发布Docker时,使用Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base MAINTAINER lihongyuan LABEL description="this is a test website" LABEL version="1.0" # ENV TimeZone=Asia/Shanghai # RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone WORKDIR /app COPY . . EXPOSE 80 ENTRYPOINT ["dotnet", "GrpcTempServer.dll"]
创建容器:
docker run --name mydemo -d -p 14421:80 imagedemo
五. webApi 项目整合 Grpc 框架
1. 增加配置项
在文件 appsettings.json 中,webapi中不能这么配置,想其他办法,需为webapi开启http2
"AllowedHosts": "*", "Kestrel": { "EndpointDefaults": { "Protocols": "Http2" } }
2. 安装插件包
3. 定义Grpc 服务
在项目中创建gRPC服务的.proto
文件。例如,增加文件夹 Protos,创建一个名为greet.proto
的文件,并定义你的服务和方法。
syntax = "proto3"; option csharp_namespace = "RailAssist.Grpc"; package greet; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply); } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings. message HelloReply { string message = 1; }
4. 生成 Grpc 代码
使用Grpc.Tools
包中的工具将.proto
文件编译成C#代码。在你的项目文件中添加以下项以启用代码生成,打开项目的 .csproj 文件
<ItemGroup> <Protobuf Include="Protos\greet.proto" GrpcServices="Server" /> </ItemGroup>
这将会自动将.proto
文件编译成C#代码,并放置在指定的输出目录中(通常是obj\Debug\net6.0\Protos
)。
5. 实现 Grpc 服务
创建 GrpcService 文件夹,创建 GreeterService.cs 文件
using Grpc.Core; using RailAssist.Grpc; namespace RailAssist.Controllers.GrpcService; public class GreeterService : Greeter.GreeterBase { private readonly ILogger<GreeterService> _logger; public GreeterService(ILogger<GreeterService> logger) { _logger = logger; } public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) { return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); } }
6. 在 Program.cs 中配置gRPC服务和中间件
builder.Services.AddGrpc();
app.MapGrpcService<GreeterService>();
7. 测试
六. 客户端项目
1. 创建控制台项目:NETCORE.GrpcCli 然后把服务端的这个文件夹整体拿过来放在客户端下面ent
安装如下三个Nuget包
Google.Protobuf
Grpc.Net.Client
Grpc.Tools
2. 客户端项目修改
把服务端的 Protos 文件夹 复制到客户端项目下面(这个意思就是,他们有共同的协议,就互通了)
双击客户端项目名称文件,即 NETCORE.GrpcClient.csproj 文件,调整配置项
<ItemGroup> <Protobuf Include="Protos\greet.proto" GrpcServices="Client" /> </ItemGroup>
3. 接口调用
在客户端中 Program.cs 编写方法调用 服务端接口,注意接口使用服务端接口
// See https://aka.ms/new-console-template for more information using Grpc.Net.Client; using NETCORE.GrpcService; Console.WriteLine("Hello, World!"); string url = "https://localhost:7180"; //https using (var channel = GrpcChannel.ForAddress(url)) { var client = new Greeter.GreeterClient(channel); var reply = client.SayHello(new HelloRequest() { Name = "故里2130" }); Console.WriteLine($"结果:message:{reply.Message}"); } Console.ReadKey(); //AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //http调用 //string url = "http://localhost:5000"; //using (var channel = GrpcChannel.ForAddress(url)) //{ // var client = new Greeter.GreeterClient(channel); // var reply = client.SayHello(new HelloRequest() // { // Name = "故里2130" // }); // Console.WriteLine($"结果:message:{reply.Message}"); //} //Console.ReadKey();
4. 测试
在启动服务端的前提下,启动客户端,接口调用完成,输出结果。
这样就完成了简单的使用过程,和webapi的效果差不多。但是它的速度远远大于webapi。
引用:https://www.jb51.net/aspnet/288820mey.htm