0%

[DotnetCore]gRPC101: Gretting專案-Server篇

前情提要

筆者因公司內部系統規劃,會有一個中台系統,負責共用的一些寄電子信件,寄簡訊,或其他共用服務,這種微服務概念而個別建立的系統,與其他系統最直觀的串接方式為Restful API, 當然還有一個GraphQL這個選擇,其特色為由前端決定回傳的資料結構,但筆者熟悉的dotnet生態圈一直沒有紅起來的感覺(或許是筆者見識淺薄),gRPC尚未出現前,這兩種都是上等之選,gRPC問世後,有一種橫空出世的感覺,因尚未支援瀏覽器端,以微服務(後端)之間串接來說,已經是一時之選。

內容

gRPC介紹

RPC這個技術早在幾十年前就有了,gRPC這個傳輸技術則由Google於2016年8月首次發佈,是基於Http/2協定傳輸,以Protocol Buffers當作介面描述語言,筆者會再另外寫一篇介紹其Protocol Buffers語言。主要特色為因有各個程式語言皆有實作版本,最大的好處是不同程式語言實作的微服務系統間可透過gRPC串接,當然也可透過Restful API串接,但gRPC優勢在於先不說其效能,因透過proto檔案,可以點出其呼叫方法,效能部份,因為Restful API是透過json格式文字傳輸,gRPC則使用小型二進位形式,其他比較參考如下:

功能 gRPC 使用 Json的HTTP API
合約 必要 (.proto) 選擇性 (OpenAPI)
通訊協定 HTTP/2 HTTP
Payload Protobuf(小型二進位) JSON (大型、人類可讀)
規範性 嚴格規格(透過protocol buffers介面語言) 鬆散。 任何 HTTP 都是有效的。
串流 用戶端、伺服器、雙向 用戶端、伺服器
瀏覽器支援 No(需要grpc-web) Yes
安全性 傳輸 (TLS) 傳輸 (TLS)
用戶端程式代碼產生 OpenAPI + 協力廠商工具

Gretting專案:Server

Microsoft Learn上的Server版本為透過dotnet new grpc建出來的,但照著做會太無聊了,且不知道其中的關係,筆者這邊就模仿其範本專案,自刻一個gRPC Server版本的專案,就跟著筆者一起開始吧。

建立web空專案

因為要使用gRPCServer,不需要APIMVC的任何設定,只要一個web空專案即可,再加上gRPC設定就好

1
2
3
mkdir GRPC.Demo
cd GRPC.Demo
dotnet new web -o GRPC.Demo.Server

加入gRPC Server所需套件

接著要來裝gRPC Server所需要的套件了,模仿grpc模板專案建出來的,要安裝的套件為Grpc.AspNetCore

1
2
cd GRPC.Demo.Server
dotnet add package Grpc.AspNetCore

增加gRPC設定

接著來改造program.cs,增加gRPC所需設定

1
2
3
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc(); //增加此行,意即加入gRPC服務
var app = builder.Build();

製作proto檔案

gRPC中最重要的proto檔案,介面規格檔案,筆者這邊也透過dotnet指令來新增其proto檔案

1
2
3
mkdir protos
cd Protos
dotnet new proto -n greet -p:n GRPC.Demo.Server

新增完成後會得到以下內容之proto檔案

1
2
3
syntax = "proto3";
// 此行為上方指令中的-p:n這個option對應的namespace設定值
option csharp_namespace = "GRPC.Demo.Server";

定義proto檔案

接著按照grpc模板專案中預設Greeter這個service

  • HelloRequest定義
1
2
3
message HelloRequest{
string name = 1;
}
  • HelloReply定義
1
2
3
message HelloReply{
string message = 1;
}
  • Greeter定義

定義好RequestResponse物件後,撰寫主要方法

1
2
3
service Greeter{
rpc SayHello(HelloRequest) returns (HelloReply);
}

Gretter這個Service中有一個方法叫SayHello,其中InputHelloRequest結構,OutputHelloReply結構,完整程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
syntax = "proto3";

option csharp_namespace = "GRPC.Demo.Server";

service Greeter{
rpc SayHello(HelloRequest) returns (HelloReply);
}

message HelloRequest{
string name = 1;
}

message HelloReply{
string message = 1;
}

編譯proto檔案

筆者這邊純手工方式完成編譯proto檔案過程,筆者起初還有點搞錯方向,想要透過vscode中的Extension來完成,無奈找了幾個,或許筆者不會設定,皆未成功,後來搜尋google後找到dotnet tool:dotnet-grpc,首先透過dotnet指令安裝tool

1
dotnet tool install -g dotnet-grpc

接著將proto檔案加入至csproj檔案的宣告中,透過上方安裝好的dotnet-grpc

1
2
# 已經於GRPC.Demo.Server路徑中
dotnet-grpc add-file -p GRPC.Demo.Server.csproj -s Server Protos\greet.proto

分段解釋一下上方指令

  • -p: 指定project
  • -s: 指定其服務類型,有BothClientDefaultNoneServer,這邊為Server,因此填寫Server
  • 最後附上proto檔案路徑

依照上方指令,會在對應的csproj檔案中多出以下設定

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

到這邊就完美Ending了,只要透過dotnet build這個指令就會完成編譯proto檔案作業

1
dotnet build

編譯後的檔案位於obj>Debug>{Target framework}>Protos

建立實作Service

到這邊只是把規格定義的作業完成,因為此篇為Server篇,需要實作其對應Service

1
2
3
mkdir Services
cd Services
touch GretterService.cs

撰寫實作Service

到這一步之前一定要完成編譯proto檔案的動作,才會有強型別可以用,馬上來感受一下

1
2
3
4
5
6
7
8
9
10
11
public class GretterService : Greeter.GreeterBase // 只要編譯過proto檔案則可以點出Gretter
{
// 透過override方式實作
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = $"Hello {request.Name}"
});
}
}

註冊實作Service

program.cs中增加一行

1
2
3
4
5
6
using GRPC.Demo.Server.Services;

// 以上省略
var app = builder.Build();
app.MapGrpcService<GretterService>();
// 以下省略

結論

gRPC Server實作到這邊告一段落了,給筆者一種感覺是gRPC傳輸技術,透過proto定義其交換規格,跟平常定義Interface一樣,只是不同的是要透過proto介面語言來撰寫,再來實作方式透過override完成,像是ChildClass中對BaseClassvirtual方法實作一般,滿好理解的,實作這端就完全沒有任何限制,若有看grpc模板專案建出來的就知道,有透過Construtor引入其ILogger,基本上DI支援也是有的,那跟撰寫一般Service層的程式並無不同,效能加上強型別,筆者會在內部系統串接時會願意試看看,這篇就到這邊了,下篇見。

參考