Net Core Grpc - 01. WebApi整合gRPC并简单调用

Net Core gRPC 系列

1. 基础包导入

.csproj
1
2
3
4
5
6
<PackageReference Include="Grpc.AspNetCore" Version="2.34.0" />
<PackageReference Include="Grpc.Core" Version="2.34.0" />
<PackageReference Include="Grpc.Tools" Version="2.34.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

2. 创建proto文件

WebApi 项目根目录下创建 Protos 文件夹。添加文件 xxx.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//proto协议
syntax = "proto3";
// csharp 命名空间
option csharp_namespace = "WebApi.Protos";
// java 命名空间
package greet;
// 导入常用类型包
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/any.proto";

// 定义接口
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;
}

proto类型可以详见官方文档 - 为 .NET 应用创建 Protobuf 消息

3. 指定项目为服务端

.csproj
1
2
3
<ItemGroup>
<Protobuf Include="Protos\Greet.proto" GrpcServices="Server" />
</ItemGroup>

在项目的.csproj文件中指定当前的proto文件生成服务端代码

4. 实现接口

proto文件实际上定义的是接口以及接口使用的数据类型。在编译项目后,通过导入的nuget包工具会生成对应的cs代码。具体位置在obj目录中。
代码也只是将proto文件转换为csharp对应的接口和抽象类。具体业务逻辑需要自定义service类来实现。接口的入参和出参都必须是message类型而不能是基本数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using Newtonsoft.Json;
using WebApi.Protos;

namespace WebApplication1Test;

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 webApi " + request.Name
});
}
}

接口实现了proto文件当中定义的接口方法SayHello,方法入参为 HelloRequest 对象,该对象是一个message类型。方法返回 HelloReply 对象,同样也是message对象。此时服务端代码完成。

5. 客户端导入nuget包

.csproj
1
2
3
4
5
6
7
8
<PackageReference Include="Google.Protobuf" Version="3.13.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.34.0" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.32.0" />
<PackageReference Include="Grpc.Tools" Version="2.32.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

6. 客户端创建protos文件夹并以link的形式引入proto文件,并指定当前为client客户端

.csproj
1
2
3
4
5
6
<ItemGroup>
<Protobuf Include="..\WebApplication1Test\Protos\greet.proto" GrpcServices="Client">
<Link>Protos\greet.proto</Link>
</Protobuf>
</ItemGroup>

7. 调用gRPC接口

1
2
3
4
5
6
7
8
9
10
//创建客户端与服务端的通道
var channel = GrpcChannel.ForAddress("http://localhost:5004");
//调用服务端接口
var helloReply = client.SayHelloAsync(new HelloRequest
{
Name = "odin-sam"
});
var resultOnce = await helloReply;
// 输出调用结果
Console.WriteLine(resultOnce.Message);

完整代码可以在 GitHub

WebApplication1Test 整合了gRPC,ConsoleApp1Test有具体调用示例