前情提要
筆者因公司內部系統規劃,會有一個中台系統,負責共用的一些寄電子信件,寄簡訊,或其他共用服務,這種微服務概念而個別建立的系統,與其他系統最直觀的串接方式為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