官方文档中关于在 Asp.Net Core 项目中使用 gRPC 的介绍已经很详细了,但是个人觉得漏了一点比较关键的信息。所以这里通过一个示例项目介绍一下如何在 Asp.Net Core 项目中使用 gRPC。
在 WebApi 项目中添加 gRPC 服务
创建两个 WebAPI 项目(ApiOne & ApiTwo),创建选项中启用 https 支持。在 ApiOne 中引用 NuGet 包:Grpc.AspDotNetCore,需要 .NET Core SDK >= 3.0 。
新增 Protos 文件夹,创建一个 Introduce.proto 文件。在 VS 中新增文件选项没有 proto 这一类型,所以是通过新增一个类文件然后改后缀这种方式。
syntax = "proto3"; option csharp_namespace = "ApiOne.Protos"; package Intro; message IntroRequest { string name = 1; } message IntroResponse { string msg = 1; } service IntroduceService{ rpc SayHi(IntroRequest) returns (IntroResponse); }
我说的比较关键的信息就是编译选项,Introduce.proto 文件属性中将 Build Action 选择 Protobuf compiler,然后多出一个 gRPC 属性,由于示例只是和官网一样的 greet 服务,我考虑在两个 api 中互相调用 rpc 服务,这里我选择 Client and Server。项目文件中会添加一项 ItemGroup。
"Microsoft.NET.Sdk.Web"> netcoreapp3.1 "Protos\Introduce.proto" /> "Grpc.AspNetCore" Version="2.30.0" /> Protos\Introduce.proto" GrpcServices="Both" /> "
此时编译一下 ApiOne,会在 \obj\Debug\netcoreapp3.1 目录下生成 Introduce.cs 和 IntroduceGrpc.cs 两个文件。
新增一个 APiIntroduceService。
using ApiOne.Protos; using Grpc.Core; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace ApiOne.Services { public class ApiIntroduceService:IntroduceService.IntroduceServiceBase { private readonly ILogger_logger; public ApiIntroduceService(ILogger logger) { _logger = logger; } public override Task SayHi(IntroRequest introRequest,ServerCallContext context) { _logger.LogInformation("rpc call IntroduceService..."); return Task.FromResult(new IntroResponse { Msg = "Hi," + introRequest.Name + ",I'm ApiOne" }); } } }
在 Startup.cs 中注册 gRPC 服务。
客户端调用 gRPC 服务
目前为止,ApiOne 的 gRPC 服务就算写好了,ApiTwo 作为客户端来调用 ApiOne 的 rpc 服务。首先在 ApiTwo 项目中引入 ApiOne 的 Introduce.proto,引入方式有多种,可以直接将 ApiOne 的 Protos 文件夹复制到 ApiTwo 项目,也可以通过服务引用方式,还可以将 protos 封装在一个单独的类库中,发布到私有 NuGet 服务器,通过 NuGet 包引用。
在 ApiTwo 项目中,依赖项右键,选择“添加连接的服务”。
选择 gRPC
可以通过将 proto 文件发布到公网环境来引用,也可以浏览本地文件。
引用文件会自动安装相关的依赖包。
在 ApiTwo 项目新增一个调用 ApiOne rpc 服务的方法。
多项目启动,访问 ApiTwo 的 GrpcCall 方法,ApiTwo 作为 RPC 服务 Introduce 的客户端去调用 Introduce 的服务端 ApiOne。
同理,按上述操作将 ApiTwo 作为 rpc 服务端,ApiOne 一样可以得到响应。