.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
.NET Core ? gRPC
千呼萬喚的 .NET Core 3.0 終于在 9 月份正式發(fā)布,在它的眾多新特性中,除了性能得到了大大提高,比較受關(guān)注的應(yīng)該是 ASP.NET Core 3.0 對(duì) gRPC 的集成了。它的源碼托管在 grpc-dotnet 這個(gè) Github 庫中,由微軟 .NET 團(tuán)隊(duì)與谷歌 gRPC 團(tuán)隊(duì)共同維護(hù).
.NET Core 對(duì) gRPC 的支持在 grpc 官方倉庫早已有實(shí)現(xiàn)(grpc/csharp),但服務(wù)端沒有很好地與 ASP.NET Core 集成,使用起來還需要自己進(jìn)行一些集成擴(kuò)展。而 ASP.NET Core 3.0 新增了 gRPC 服務(wù)的托管功能,能讓 gRPC 與 ASP.NET Core 框架本身的特性很好地結(jié)合,如日志、依賴注入、身份認(rèn)證和授權(quán),并由 Kestrel 服務(wù)器提供 HTTP/2 鏈接,性能上得到充分保障。
推薦把項(xiàng)目中已有的 RPC 框架或者內(nèi)部服務(wù)間 REST 調(diào)用都遷移到 gRPC 上,因?yàn)樗呀?jīng)是云原生應(yīng)用的標(biāo)準(zhǔn) RPC 框架,在整個(gè) CNCF 主導(dǎo)下的云原生應(yīng)用開發(fā)生態(tài)里 gRpc 有著舉足輕重的地位。
對(duì)于 gRPC 的使用方式,前段時(shí)間已經(jīng)有其他大神寫的幾篇文章了,這里就不再贅述了。本文主要介紹的是區(qū)別于標(biāo)準(zhǔn)使用規(guī)范的,但對(duì).NET 應(yīng)用更加友好的使用方式,最后會(huì)提供源碼來展示。
作為對(duì)比,還是要列一下標(biāo)準(zhǔn)的使用步驟:
定義 proto 文件,包含服務(wù)、方法、消息對(duì)象的定義
引入 Grpc.Tools Nuget 包并添加指定 proto 路徑和生成模式
生成項(xiàng)目,得到服務(wù)端的抽象類或客戶端的調(diào)用客戶端組件
實(shí)現(xiàn)服務(wù)端抽象類,并在 ASP.NET Core 注冊這個(gè)服務(wù)的路由端點(diǎn)
DI 注冊 gRPC 服務(wù)。
客戶端用 Grpc.Net.ClientFactory Nuget 包進(jìn)行統(tǒng)一配置和依賴注入
.NET Core 對(duì) gRPC 的大力支持使開發(fā)者開發(fā)效率大大提高,入門難度也減少了許多,完全可以成為跟 WebApi 等一樣的 .NET Core 技術(shù)棧的標(biāo)配。
proto 在單一語言系統(tǒng)架構(gòu)中的局限性
使用 proto 文件的好處是多語言支持,同一份 proto 可以生成各種語言的服務(wù)和客戶端,可以讓用不同語言開發(fā)的微服務(wù)直接互相遠(yuǎn)程調(diào)用。但 proto 文件作為不同服務(wù)間的契約,不可以經(jīng)常修改,否則就會(huì)對(duì)使用了它的服務(wù)造成不同程度的影響,因此對(duì) proto 文件的版本控制需要得到重視。
另外,我們的應(yīng)用程序還不應(yīng)該與 gRPC 耦合,否則就會(huì)導(dǎo)致系統(tǒng)架構(gòu)被這些實(shí)現(xiàn)細(xì)節(jié)所綁架。直接依賴 proto 文件和由它生成的代碼,就是對(duì) gRPC 的強(qiáng)耦合。
例如,當(dāng)應(yīng)用程序在演進(jìn)的過程中,復(fù)雜度還未達(dá)到完全部署隔離的必要時(shí),為了避免因“完全邊界”引入的部署運(yùn)維復(fù)雜性,又能預(yù)留隔離的可能性,需要有一層接口層作為“不完全邊界”。
又比如,目前在 windows 系統(tǒng)的 iis 上還不支持 grpc-dotnet,當(dāng)有 windows 上的應(yīng)用程序需要使用 RPC,就需要換成 REST 的實(shí)現(xiàn)了。
因此,為了不讓應(yīng)用程序?qū)?gRPC 過于依賴,還應(yīng)該使用一層抽象(接口)層與其解耦,用接口來隔離對(duì) RPC 實(shí)現(xiàn)的依賴,這樣在需要使用不同的實(shí)現(xiàn)時(shí),可以通過注冊不同的實(shí)現(xiàn)來方便地切換。
在這些場景下,本文要介紹的 Code-First gRPC 使用方法就發(fā)揮作用了。
Code-First gRPC
說了這么久,我好像還沒正式介紹 Code-First gRPC,到底他有多適合在單一語言系統(tǒng)架構(gòu)中實(shí)現(xiàn) gRPC 呢?下面要介紹的就是基于大名鼎鼎的 protobuf-net 實(shí)現(xiàn)的 gRPC 框架,protobuf-net.Grpc。
protobuf-net 是在過去十幾年前到現(xiàn)在一直在 .NET 中有名的 Protobuf 庫,想用 Protobuf 序列化時(shí)就會(huì)用到這個(gè)庫。他的特性就是可以把 C# 代碼編寫的類能以 Protobuf 的協(xié)議進(jìn)行序列化和反序列化,而不是 proto 文件再生成這些類。而 protobuf-net.Grpc 則是一脈相承,可以把 C# 寫的接口,在服務(wù)端方便地把接口的實(shí)現(xiàn)類注冊成 ASP.NET Core 的 gRPC 服務(wù),在客戶端把接口動(dòng)態(tài)代理實(shí)現(xiàn)為調(diào)用客戶端,調(diào)用前面的這個(gè)服務(wù)端。
用法很簡單,只要聲明一個(gè)接口為您的服務(wù)契約:
[ServiceContract]public interface IMyAmazingService {
ValueTask<SearchResponse> SearchAsync(SearchRequest request);
// ...
}
然后實(shí)現(xiàn)該接口的服務(wù)端:
public class MyServer : IMyAmazingService {// ...
}
或者向系統(tǒng)獲取客戶端:
var client = http.CreateGrpcService<IMyAmazingService>();var results = await client.SearchAsync(request);
這相當(dāng)于以下 .proto 中的服務(wù):
service MyAmazingService {rpc Search (SearchRequest) returns (SearchResponse) {}
// ...
}
protobuf-net.Grpc 同樣通過普通類型定義支持 gRPC 的四種模式,把 C# 8.0 中最新的 IAsyncEnumerable 類型識(shí)別成 proto 中的 stream,單向流、雙向流都可以實(shí)現(xiàn)!而且用 IAsyncEnumerable 實(shí)現(xiàn)可比 proto 生成的類方便很多。
例如 proto 雙向流定義:
rpc chat(stream ChatRequest) returns ( stream ChatResponse);生成出來的方法是:
Task BathTheCat(IAsyncStreamReader<ChatRequest> requestStream, IServerStreamWriter<ChatResponse> responseStream)而 protobuf-net.Grpc 只要定義一個(gè)方法:
IAsyncEnumerable<ChatResponse> SubscribeAsync(IAsyncEnumerable<ChatRequest> requestStream);總結(jié)
由此可見,protobuf-net.Grpc 無需在契約層引入第三方庫,充分運(yùn)用了 C# 類型系統(tǒng),把方法、類型映射到兼容了 gRPC 的服務(wù)定義上。
上文所說的 proto 局限也迎刃而解了,函數(shù)調(diào)用、gRPC、REST 都能方便切換。(REST 實(shí)現(xiàn)可以參考我的開源框架 shriek-fx 中的 Shriek.ServiceProxy.Http )組件。
下一篇,我將主要介紹利用 protobuf-net.Grpc 的 gRPC 雙向流模式與 Blazor 實(shí)現(xiàn)一個(gè)簡單的在線即時(shí)聊天室。
相關(guān)鏈接:
- protobuf-net.Grpc:https://github.com/protobuf-net/protobuf-net.Grpc 
- shriek-fx:https://github.com/Shriek-Projects/shriek-fx 
- GrpcChat: https://github.com/ElderJames/GrpcChat 
總結(jié)
以上是生活随笔為你收集整理的.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: .NET做人脸识别并分类
- 下一篇: dotnet Blazor 用 C# 控
