前情提要
筆者因公司內部系統規劃,會有一個中台系統,負責共用的一些寄電子信件,寄簡訊,或其他共用服務,這種微服務概念而個別建立的系統,與其他系統最直觀的串接方式為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空專案
因為要使用gRPC
的Server
,不需要API
或MVC
的任何設定,只要一個web空專案即可,再加上gRPC
設定就好
1 | mkdir GRPC.Demo |
加入gRPC Server所需套件
接著要來裝gRPC Server
所需要的套件了,模仿grpc模板專案建出來的,要安裝的套件為Grpc.AspNetCore
1 | cd GRPC.Demo.Server |
增加gRPC設定
接著來改造program.cs
,增加gRPC
所需設定
1 | var builder = WebApplication.CreateBuilder(args); |
製作proto檔案
gRPC
中最重要的proto
檔案,介面規格檔案,筆者這邊也透過dotnet
指令來新增其proto
檔案
1 | mkdir protos |
新增完成後會得到以下內容之proto
檔案
1 | syntax = "proto3"; |
定義proto檔案
接著按照grpc
模板專案中預設Greeter
這個service
吧
- HelloRequest定義
1 | message HelloRequest{ |
- HelloReply定義
1 | message HelloReply{ |
- Greeter定義
定義好Request
跟Response
物件後,撰寫主要方法
1 | service Greeter{ |
Gretter
這個Service
中有一個方法叫SayHello
,其中Input
為HelloRequest
結構,Output
為HelloReply
結構,完整程式碼如下:
1 | syntax = "proto3"; |
編譯proto檔案
筆者這邊純手工方式完成編譯proto
檔案過程,筆者起初還有點搞錯方向,想要透過vscode
中的Extension
來完成,無奈找了幾個,或許筆者不會設定,皆未成功,後來搜尋google
後找到dotnet tool
:dotnet-grpc
,首先透過dotnet
指令安裝tool
1 | dotnet tool install -g dotnet-grpc |
接著將proto
檔案加入至csproj
檔案的宣告中,透過上方安裝好的dotnet-grpc
1 | # 已經於GRPC.Demo.Server路徑中 |
分段解釋一下上方指令
-p
: 指定project
-s
: 指定其服務類型,有Both
,Client
,Default
,None
,Server
,這邊為Server,因此填寫Server
- 最後附上
proto
檔案路徑
依照上方指令,會在對應的csproj
檔案中多出以下設定
1 | <ItemGroup> |
到這邊就完美Ending了,只要透過dotnet build
這個指令就會完成編譯proto
檔案作業
1 | dotnet build |
編譯後的檔案位於obj>Debug>{Target framework}>Protos
建立實作Service
到這邊只是把規格定義的作業完成,因為此篇為Server
篇,需要實作其對應Service
1 | mkdir Services |
撰寫實作Service
到這一步之前一定要完成編譯proto
檔案的動作,才會有強型別可以用,馬上來感受一下
1 | public class GretterService : Greeter.GreeterBase // 只要編譯過proto檔案則可以點出Gretter |
註冊實作Service
於program.cs
中增加一行
1 | using GRPC.Demo.Server.Services; |
結論
gRPC Server
實作到這邊告一段落了,給筆者一種感覺是gRPC
傳輸技術,透過proto
定義其交換規格,跟平常定義Interface
一樣,只是不同的是要透過proto
介面語言來撰寫,再來實作方式透過override
完成,像是ChildClass
中對BaseClass
的virtual
方法實作一般,滿好理解的,實作這端就完全沒有任何限制,若有看grpc模板專案建出來的就知道,有透過Construtor引入其ILogger
,基本上DI
支援也是有的,那跟撰寫一般Service
層的程式並無不同,效能加上強型別,筆者會在內部系統串接時會願意試看看,這篇就到這邊了,下篇見。
參考
- https://learn.microsoft.com/zh-tw/aspnet/core/grpc/comparison?view=aspnetcore-7.0
- https://learn.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-7.0