日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET Core使用gRPC打造服务间通信基础设施

發(fā)布時間:2023/12/4 asp.net 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET Core使用gRPC打造服务间通信基础设施 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、什么是RPC

rpc(遠程過程調(diào)用)是一個古老而新穎的名詞,他幾乎與http協(xié)議同時或更早誕生,也是互聯(lián)網(wǎng)數(shù)據(jù)傳輸過程中非常重要的傳輸機制。

利用這種傳輸機制,不同進程(或服務(wù))間像調(diào)用本地進程中的方法一般進行交互,而無需關(guān)心實現(xiàn)細節(jié)。

rpc的主要實現(xiàn)流程為:

圖片

1、客戶端本地方法調(diào)用客戶端stub(方法存根)。這個調(diào)用發(fā)生在客戶端本地,并把調(diào)用參數(shù)推送到棧中。

2、客戶端stub (方法存根)將這些參數(shù)打包,通過系統(tǒng)調(diào)用發(fā)送到服務(wù)器機器。打包的過程通常可以采用xml、json、二進制編碼。打包的過程被稱為marshalling。

3、客戶端本地操作系統(tǒng)發(fā)送信息到目標(biāo)服務(wù)器(可以通過自定義tcp協(xié)議或Http協(xié)議傳輸)。

4、服務(wù)器系統(tǒng)將信息傳送到服務(wù)端stub(方法存根)

5、服務(wù)端stub (服務(wù)端方法存根) 解析信息。解析信息的過程可以稱為 unmarshalling。

6、服務(wù)器stub (服務(wù)端方法存根) 調(diào)用程序,并通過類似的方式返回客戶端。

為了讓不同的客戶端均能訪問服務(wù)器,許多標(biāo)準(zhǔn)化的rpc組件往往會使用接口描述語言的形式,以便方便跨平臺、跨語言的遠程過程調(diào)用的實現(xiàn)。

圖1:RPC 調(diào)用流程

參考維基百科:https://zh.wikipedia.org/wiki/%E9%81%A0%E7%A8%8B%E9%81%8E%E7%A8%8B%E8%AA%BF%E7%94%A8

二、什么時候使用RPC?

HTTP和RPC是現(xiàn)代微服務(wù)架構(gòu)中普遍采用的兩種數(shù)據(jù)傳輸方式,在某種場合幾乎都是可以完全替換的,但又具有各自不同的特點。

1、HTTP協(xié)議是一種規(guī)范、開放、通用性非常強、標(biāo)準(zhǔn)的傳輸協(xié)議,幾乎所有的語言都支持,如果要確保各類平臺都能無縫的訪問數(shù)據(jù),可以考慮使用HTTP協(xié)議。例如目前常用的RestFul規(guī)約,定義好請求方法、數(shù)據(jù)格式并以Json的形式返回參數(shù),能夠讓前后端之間的對接非常便捷;之前的開發(fā)者或許用wsdl、soap的形式比較多,也都是HTTP協(xié)議的應(yīng)用。

2、RPC協(xié)議不僅僅是一種服務(wù)間傳輸?shù)膮f(xié)議,也能使用于進程間的數(shù)據(jù)傳輸,它能極大的降低微服務(wù)間的通信成本,屏蔽通信細節(jié),讓調(diào)用者能夠像調(diào)用本地方法一般調(diào)用遠程方法。 相對而言,RPC可能無法在網(wǎng)頁端提供支持,也并非所有的語言都實現(xiàn)了這種接口描述語言,讓開發(fā)過程會相對繁瑣,因此它的使用范圍相對較小。雖然gRPC目前已經(jīng)提供了web版的gRPC,但由于瀏覽器的兼容性等問題,也限制了他的應(yīng)用。

三、什么是gRPC

gRPC可以通俗的理解為google實現(xiàn)的一種?RPC的形式。

參見gRPC官網(wǎng)的解釋:

gRPC是可以在任何環(huán)境中運行的現(xiàn)代開源高性能RPC框架。它可以通過可插拔的支持來有效地連接數(shù)據(jù)中心內(nèi)和跨數(shù)據(jù)中心的服務(wù),以實現(xiàn)負載平衡,跟蹤,運行狀況檢查和身份驗證。它也適用于分布式計算的最后一英里,以將設(shè)備,移動應(yīng)用程序和瀏覽器連接到后端服務(wù)。

它包括四個主要特點:

1.簡單的服務(wù)定義:gRPC基于Protobuf協(xié)議構(gòu)建,該協(xié)議提供了一個強大的二進制序列化工具集和語言定義服務(wù)。2.跨語言和平臺工作:可自動為多語言或平臺生成符合相應(yīng)習(xí)慣的客戶端和服務(wù)端存根3.快速啟動并擴展:只需一行代碼即可安裝運行時環(huán)境和生成環(huán)境、并通過該框架可擴展到數(shù)百萬rpc請求。4.雙向流和集成身份驗證:基于http/2的傳輸機制以及雙向流傳輸和完全集成的可插入式身份驗證機制。

gRPC目前廣泛應(yīng)用于各大互聯(lián)網(wǎng)公司的微服務(wù)架構(gòu)中,也是CNCF基金會孵化的開源基礎(chǔ)設(shè)施組件。其官網(wǎng)為https://grpc.io/;開源項目地址為https://github.com/grpc/grpc。

官網(wǎng)提供了詳細的文檔說明,幾乎可以開箱即用,只需簡單配置就能滿足你的應(yīng)用需求。在開源項目中也提供了完善的各種語言實現(xiàn)的sample示例代碼,能極大的方便開發(fā)者的使用。

在gRPC中,使用的傳輸協(xié)議為HTTP/2,使用的數(shù)據(jù)傳輸?shù)母袷綖镻rotobuf協(xié)議。

四、什么是Protobuf

Protobuf全稱為Protocal Buffers,是一種序列化協(xié)議實現(xiàn),與只類似的還有thrift。這是一種與語言中立、與實現(xiàn)無關(guān)、可擴展的序列化數(shù)據(jù)格式,不僅僅可以用于通信協(xié)議傳輸過程,也同樣適用于數(shù)據(jù)存儲過程。它靈活高效、性能優(yōu)良、更加快速和簡單。在使用Protobuf的實踐中,只需定義要處理數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),就能利用Protobuf生成相關(guān)的代碼。只需使用Protobuf對數(shù)據(jù)結(jié)構(gòu)進行描述(IDL),即可在各種不同的語言或不同的數(shù)據(jù)流中對結(jié)構(gòu)化數(shù)據(jù)進行輕松讀寫。

在上面的圖1 RPC調(diào)用流程中,使用紅色字體標(biāo)注的(1)中,在客戶端套接字和服務(wù)端套接字之間進行數(shù)據(jù)交換的數(shù)據(jù)傳輸機制就可以使用Protobuf。

Protocol Buffers最早是有谷歌發(fā)明用于解決索引服務(wù)器之間request/response協(xié)議的。通過慢慢發(fā)展發(fā)展和演進,目前已經(jīng)具有了更多的特性:

?自動生成的序列化和反序列化代碼避免了手動解析的需要。(官方提供自動生成代碼工具,各個語言平臺的基本都有)?除了用于 RPC(遠程過程調(diào)用)請求之外,人們開始將 protocol buffers 用作持久存儲數(shù)據(jù)的便捷自描述格式(例如,在Bigtable中)。?服務(wù)器的 RPC 接口可以先聲明為協(xié)議的一部分,然后用 protocol compiler 生成基類,用戶可以使用服務(wù)器接口的實際實現(xiàn)來覆蓋它們。

由于protocal buffers誕生之初主要是為了解決服務(wù)器新舊協(xié)議之間兼容性問題,所以命名為"協(xié)議緩沖區(qū)",不過目前顯然已經(jīng)超出了緩沖含義的范圍。而Protobuf中的術(shù)語,則使用"message"來指代在協(xié)議傳輸過程中定義的抽象化對象,也顯然不再僅僅只是原始含義的消息所能囊括的。

五、Proto3協(xié)議簡述

當(dāng)我們使用Visual Studio 2019創(chuàng)建一個.NET Core下的gRPC項目時,可以看到,項目會自帶一個Protos\Greet.proto文件,這便是gRPC使用的Protobuf的接口描述文件,通過定義這個描述文件,可以為生成對應(yīng)的服務(wù)端、客戶端方法存根,讓方法調(diào)用過程更加簡單。

1、基本的數(shù)據(jù)類型對應(yīng)關(guān)系

目前最新版本的Protobuf協(xié)議為proto3協(xié)議,在這個新版的協(xié)議中,提供了以下數(shù)據(jù)類型,可以方便的對應(yīng)到我們?nèi)粘J褂玫臄?shù)據(jù)類型。

圖片

2、關(guān)鍵字

1)分配字段編號

在proto協(xié)議中,每個消息定義中的字段都有唯一的編號,用來表示消息二進制格式中的字段,且使用消息類型后不應(yīng)更改。可以使用的最小編號為1,最大編號為2^29^-1 或 536,870,911,但不包括 19000 到 19999(FieldDescriptor :: kFirstReservedNumber 到 FieldDescriptor :: kLastReservedNumber),因為它們是為 Protocol Buffers實現(xiàn)保留的。

2)重復(fù)字段(repeated)

在消息中定義重復(fù)字段(repeated 關(guān)鍵字),允許一個message 字段中重復(fù)數(shù)值,可以理解為數(shù)組對象。

3)保留字段(reserved)

Protobuf中提供了保留字段(reserved 關(guān)鍵字),如果在老版本的proto文件中定義了一些字段,而在新版本的協(xié)議中移除了這些字段,有可能出現(xiàn)協(xié)議文件不匹配的問題,則可以使用reserved關(guān)鍵字。這樣當(dāng)協(xié)議數(shù)據(jù)不匹配時,編譯器會提示錯誤。

圖片

圖2 使用保留字段時,會提示錯誤

3、枚舉

允許在消息中定義枚舉類型。也可以將枚舉類型嵌套在message中。當(dāng)使用枚舉類型時,需要注意:

?枚舉為 0 的是作為零值,當(dāng)不賦值的時候,就會是零值。?為了和 proto2 兼容。在 proto2 中,零值必須是第一個值。

4、消息嵌套

在proto協(xié)議中,允許嵌套組合為更加復(fù)雜的消息。

message SearchResponse { repeated Result results = 1; } message Result { string url = 1; string title = 2; repeated string snippets = 3; }

5、定義服務(wù)(Services)

在proto中,如果需要對外提供接口方法,則需要使用Services。定義好services之后,protocol buffer編譯器將使用所選語言生成服務(wù)接口代碼和客戶端與服務(wù)端方法存根。例如,

service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply); }

這里就定義了一個SayHello的方法存根。該方法將返回一個名稱為 HelloReply 的消息。 如果需要定義無參數(shù)方法,或返回值為 void 的方法,需要使用 google.protobuf.Empty對象 ,表示傳輸空消息,是空的JSON對象{},并在頭部的命名空間中,引用默認的協(xié)議文件

google/protobuf/empty.proto. *例如:

option csharp_namespace = "TestGRPC_Client"; import "google/protobuf/empty.proto"; package Greet; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply); rpc Listen (google.protobuf.Empty) returns (google.protobuf.Empty);//啟動監(jiān)聽 }

同樣,也可以使用 import 引用其他協(xié)議文件。 參考《https://github.com/halfrost/Halfrost-Field/blob/master/contents/Protocol/Protocol-buffers-encode.md》

六、什么是HTTP/2

gRPC 的客戶端與服務(wù)端之間的通信機制,并沒有采用TCP造輪子,而是重用了HTTP/2的傳輸協(xié)議。HTTP2.0是超文本傳輸協(xié)議HTTP的下一代協(xié)議,也是在傳統(tǒng)開發(fā)者最為熟悉的HTTP/1.1 協(xié)議格式基礎(chǔ)上進行的升級。 與1.1相比,他提供了新的二進制格式、多路復(fù)用機制、Header壓縮、服務(wù)端推送等特色,讓協(xié)議請求過程能夠達到更好的性能提升。限于篇幅,這里就不再贅述了。

七、服務(wù)端開發(fā)

我們將引入一個范例,以HelloWorld作為項目名稱,在這個項目中,簡單介紹在NetCore中如何使用gRPC的過程、如何使用gRPC進行簡單身份驗證的過程。

服務(wù)端:

?并提供一個登錄 login 的方法、以及其配套的用戶請求參數(shù)、并返回對應(yīng)的響應(yīng)值。?一個 logout 的方法,該方法返回值為void空對象。

1、創(chuàng)建項目

在Visual Studio 2019中創(chuàng)建一個基于gRPC的空項目。這個項目命名為HelloWorld,放置在默認目錄下。如果有需要可以開啟容器支持。

圖片

圖片

圖片

2、項目的組成結(jié)構(gòu)

當(dāng)我們查看這個項目時,可以看到這是一個Asp.NET Core的項目,默認的項目模板中已經(jīng)集成了Asp.NET Core和gRPC.AspNetCore的組件包。

圖片

?Protos文件夾

后綴名為proto的是基于proto3的協(xié)議文件。

圖片

?Services文件夾

項目模板創(chuàng)建的默認請求文件,實現(xiàn)了在proto文件中定義的SayHello方法,并以異步的形式返回了對象HelloReply。

圖片

?其他文件

Dockerfile:模板自動創(chuàng)建的Dockerfile文件,后期可以基于這個文件進行docker容器的構(gòu)建。

Program: 程序運行的入口。

Startup: 程序啟動項,定義AspNET Core項目啟動所需的各種配置信息。 在UseRouting和UseEndPoints中間,加入UseAuthentication()和UseAuthorization()代碼,以便為后期身份認證和授權(quán)。。

圖片

3、創(chuàng)建Proto文件

在Protos文件夾右鍵單擊,創(chuàng)建一個空的記事本文件(快捷鍵為Ctrl+Shift+A),命名為helloworld.proto。然后再里面鍵入以下內(nèi)容:

syntax = "proto3" import "google/protobuf/empty.proto"; //需要使用空參數(shù)和空返回值時,需要使用這個默認的協(xié)議文件 option csharp_namespace="HelloWorld"; package Account; service Account{ rpc Login (LoginModel) returns (UserModel); rpc Logout (google.protobuf.Empty) returns (google.protobuf.Empty); } message LoginModel{ string userName=1; string userPsw=2; } message UserModel{ string NickName=1; string Token=2; Date LoginDate=3; } message Date{ int32 Year=1; int32 Month=2; int32 Day=3; int32 Hour=4; int32 Minute=5; int32 Second=6; int32 FFF=7; }

4、創(chuàng)建 AccountService文件

選擇 Services 文件夾,并創(chuàng)建一個文件名為 AccountService的CSharp代碼文件。并分別重載 Login 和 Logout 方法。

public class AccountService : account.accountBase { public override Task<UserModel> Login(LoginModel request, ServerCallContext context) { return base.Login(request, context); } public override Task<Empty> Logout(Empty request, ServerCallContext context) { return base.Logout(request, context); } }

然后再進行代碼的編寫。這里我們將登錄后,返回一個假的 UserModel 數(shù)據(jù)。除此之外,我們還返回了錯誤情況下的返回模型 BadRequest 。

public class AccountService : account.accountBase { public override Task<StringData> Login(LoginModel request, ServerCallContext context) { if (request.UserName == "1234" && request.UserPsd == "1234") { var userModel = new UserModel { NickName = "測試用戶", Token = Guid.NewGuid().ToString(), }; return Task.FromResult(new StringData() { Data = Newtonsoft.Json.JsonConvert.SerializeObject(userModel) }); } else { var BadRequest = new BadRequest { ErrorCode = 1, ErrorDescription = "用戶名或密碼錯誤" }; return Task.FromResult(new StringData() { Data = Newtonsoft.Json.JsonConvert.SerializeObject(BadRequest) }); } } public override Task<Empty> Logout(Empty request, ServerCallContext context) { return Task.FromResult(new Empty()); } } public class BadRequest { public int ErrorCode { get; set; } public string ErrorDescription { get; set; } }

八、客戶端開發(fā)

客戶端,是一個基于 .NET Core 的控制臺程序。在這個控制臺中,我們可以實現(xiàn)下面功能:

?通過輸入命令 1 調(diào)用登錄方法;?輸入命令 2 調(diào)用登出方法。

1、創(chuàng)建項目、引用依賴包

創(chuàng)建一個基于.NET Core的一個控制臺程序,并使用 Nuget 安裝組件包

圖片

2、創(chuàng)建協(xié)議文件

將在服務(wù)端開發(fā)中創(chuàng)建的 Protos 文件夾拷貝到客戶端程序中。

圖片

并使用記事本對項目文件【HelloWorld.Client.csproj】進行編輯, 將Protobuf 文件的GrpcServices屬性設(shè)置為 “Client”。

完成這些操作,編譯完成,即可自動生成客戶端與服務(wù)端連接的客戶端方法存根。

3、編寫客戶端方法

創(chuàng)建一個單獨的類文件,用來編寫客戶端調(diào)用方法。這個類文件名稱為 AccountClientImpl。 代碼如下:

using Grpc.Net.Client; using System; using System.Collections.Generic; using System.Text; using static HelloWorld.Greeter; using System.Threading.Tasks; namespace HelloWorld.Client { public class AccountClientImpl { private readonly GrpcChannel _grpcChannel; private readonly Account.AccountClient _accountClient; public AccountClientImpl(GrpcChannel grpcChannel, Account.AccountClient accountClient) { _grpcChannel = grpcChannel; _accountClient = accountClient; } public void Login() { var result = _accountClient.Login(new LoginModel() { UserName = "1234", UserPsd = "1234" }); Console.WriteLine(result.Data); } public void Logout() { var empty = new Google.Protobuf.WellKnownTypes.Empty(); _accountClient.Logout(empty); } } }

然后再修改 Program.cs 文件,用來調(diào)用上述方法。在這個方法中,如果輸入1,則執(zhí)行登錄方法;輸入2,則執(zhí)行退出方法。

class Program { static void Main(string[] args) { var channel = GrpcChannel.ForAddress("https://localhost:5001"); var client = new Account.AccountClient(channel); AccountClientImpl accountClientImpl = new AccountClientImpl(channel, client); if (Console.ReadLine() == "1") { accountClientImpl.Login(); } else if (Console.ReadLine() == "2") { accountClientImpl.Logout(); } Console.ReadKey(); } }

這樣就完成了我們的代碼編寫。 將客戶端與服務(wù)端運行起來,然后在客戶端代碼中輸入數(shù)字 1 ;即可獲得我們想要的結(jié)果。

圖片

九、協(xié)議與項目分離

在傳統(tǒng)的開發(fā)過程中,由于客戶端和服務(wù)端需要維護兩套內(nèi)容完全相同的 proto 協(xié)議文件,略顯臃腫,因此我們可以通過相應(yīng)的手段,將對應(yīng)的文件進行分離,便于后期的維護。

1、移動文件

將服務(wù)端中的Protos文件移動到上一級目錄。

圖片

2、修改項目文件中的Proto文件

服務(wù)端修改為:

<ItemGroup> <Protobuf Include="..\Protos\*.proto" GrpcServices="Server" /> <Content Include="@(Protobuf)" LinkBase="" /> </ItemGroup>

客戶端修改為:

<ItemGroup> <Protobuf Include="..\Protos\*.proto" GrpcServices="Client" /> <Content Include="@(Protobuf)" LinkBase="" /> </ItemGroup>

圖片

如果覺得這樣的展示效果不太美觀,也可以將proto文件移動到Protos目錄下。

3、重新編譯

完成協(xié)議文件分離,即可對項目進行編譯。

總結(jié)

在這個教程中,我們從PRC開始講起,簡單介紹了與gRPC相關(guān)的技術(shù)棧,練習(xí)了使用 gRPC 進行服務(wù)端和客戶端程序開發(fā)的全過程,希望大家能獲得收獲。

第一次嘗試編寫入門級教程,如有不足之處還請批評指正。

總結(jié)

以上是生活随笔為你收集整理的.NET Core使用gRPC打造服务间通信基础设施的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。