圖析ASP.NET Core引入gRPC服務(wù)模板
早就聽說(shuō)ASP.NET Core 3.0中引入了gRPC的服務(wù)模板,正好趁著家里電腦剛做了新系統(tǒng),然后裝了VS2019的功夫來(lái)體驗(yàn)一把。同時(shí)記錄體驗(yàn)的過(guò)程。如果你也想按照本文的步驟體驗(yàn)的話,那你得先安裝.NET Core3.0預(yù)覽版的SDK。至于開發(fā)工具我用的時(shí)VS2019,當(dāng)然你也可以使用VS Code進(jìn)行。
gRPC的簡(jiǎn)單介紹
gRPC 是一種與語(yǔ)言無(wú)關(guān)的高性能遠(yuǎn)程過(guò)程調(diào)用 (RPC) 框架。 有關(guān) gRPC 基礎(chǔ)知識(shí)的詳細(xì)信息,請(qǐng)參閱 gRPC 文檔頁(yè)。
gRPC 的主要優(yōu)點(diǎn)是:
- 現(xiàn)代高性能輕量級(jí) RPC 框架。
- 協(xié)定優(yōu)先 API 開發(fā),默認(rèn)使用協(xié)議緩沖區(qū),允許與語(yǔ)言無(wú)關(guān)的實(shí)現(xiàn)。
- 可用于多種語(yǔ)言的工具,以生成強(qiáng)類型服務(wù)器和客戶端。
- 支持客戶端、服務(wù)器和雙向流式處理調(diào)用。
- 使用 Protobuf 二進(jìn)制序列化減少對(duì)網(wǎng)絡(luò)的使用。
這些優(yōu)點(diǎn)使 gRPC 適用于:
- 效率至關(guān)重要的輕量級(jí)微服務(wù)。
- 需要多種語(yǔ)言用于開發(fā)的 Polyglot 系統(tǒng)。
- 需要處理流式處理請(qǐng)求或響應(yīng)的點(diǎn)對(duì)點(diǎn)實(shí)時(shí)服務(wù)。
ASP.NET Core 3.0上gRPC服務(wù)模板初體驗(yàn)
創(chuàng)建gRPC服務(wù)
1 .打開VS2019 從 Visual Studio“文件”菜單中選擇“新建” > “項(xiàng)目”。(由于我是新打開的VS,所以按照如下圖所示創(chuàng)建新項(xiàng)目)

2.如下圖所示,選擇創(chuàng)建《ASP.NET Core Web 應(yīng)用程序》,然后點(diǎn)擊下一

3.在此頁(yè)面按照下圖所示,輸入項(xiàng)目名稱,位置,解決方案名稱,然后點(diǎn)擊右下角的“創(chuàng)建”按鈕進(jìn)行創(chuàng)建。

4.你以為上述步驟中點(diǎn)擊“創(chuàng)建”就結(jié)束了嘛?說(shuō)好的要?jiǎng)?chuàng)建gRPC服務(wù)模板的,所以,點(diǎn)擊上面的創(chuàng)建后會(huì)彈出如下圖所示,讓你選擇服務(wù)模板的窗口,這里按照下圖所示選擇gRPC服務(wù)模板,然后再次點(diǎn)擊右下角的創(chuàng)建,才是真正的創(chuàng)建項(xiàng)目。

5.創(chuàng)建成功后,會(huì)出現(xiàn)如下圖所示的項(xiàng)目結(jié)構(gòu)

6.至此,我們就創(chuàng)建好了一個(gè)gRPC服務(wù)的模板,接下來(lái)我們先測(cè)試一番,然后再好好的看下這個(gè)模板的結(jié)構(gòu)吧
測(cè)試gRPC服務(wù)
1.首先打開HelloGrpc.Server 這個(gè)服務(wù)端的工作目錄,然后Shift+鼠標(biāo)右鍵彈出如下圖所示的右鍵菜單,如圖所示打開ps窗口

2.輸入dotnet run 命令運(yùn)行此gRPC服務(wù)端項(xiàng)目,如下圖所示,說(shuō)明服務(wù)端啟動(dòng)正常,并開始監(jiān)聽對(duì)應(yīng)的端口。

3.同樣的方法,我們啟動(dòng)客戶端,這時(shí)候客戶端會(huì)向該服務(wù)端發(fā)送一條包含具有其名稱“GreeterClient”的消息的問(wèn)候信息。 該服務(wù)端將發(fā)送一條消息“Hello GreeterClient”作為響應(yīng),并顯示在命令提示符中。如下圖所示:

4.至此,gRPC服務(wù)模板創(chuàng)建的服務(wù)端以及客戶端測(cè)試成功。下面我們就好好的探究一下這個(gè)服務(wù)模板吧。
gRPC模板解析
在HelloGrpc.Server 服務(wù)的端項(xiàng)目中有如下幾個(gè)文件
- greet.proto:greet.proto 文件定義
GreetergRPC,且用于生成 gRPC 服務(wù)器資產(chǎn)。 - Services 文件夾:包含
Greeter服務(wù)的實(shí)現(xiàn)。 - appSettings.json:包含配置數(shù)據(jù),如 Kestrel 使用的協(xié)議。(熟悉ASP.NET Core的你一定很熟悉)
- Program.cs:包含 gRPC 服務(wù)的入口點(diǎn)。(熟悉ASP.NET Core的你一定很熟悉)
- Startup.cs:
IWebHostBuilder的啟動(dòng)配置文件,包含配置應(yīng)用行為的代碼。(熟悉ASP.NET Core的你一定很熟悉)
gRPC 客戶端 HelloGrpc.Client 文件:
Program.cs 包含 gRPC 客戶端的入口點(diǎn)和邏輯。
下面我們?cè)俅蜷_每個(gè)文件看看里面究竟是什么東東吧。
proto文件
proto
GRPC使用約定優(yōu)先的API開發(fā)方法。默認(rèn)情況下,使用協(xié)議緩沖區(qū)(Protobuf)作為接口設(shè)計(jì)語(yǔ)言(IDL)。這個(gè).proto文件包含:
- GRPC服務(wù)的定義。
- 在客戶端和服務(wù)器之間發(fā)送的消息。
有關(guān)Protobuf文件語(yǔ)法的更多信息,請(qǐng)參見正式文件(原型).
如我們模板中創(chuàng)建的greet.proto 文件內(nèi)容如下:
syntax = "proto3";
package Greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
- 定義
Greeter服務(wù)。 - 這個(gè)
Greeter服務(wù)定義SayHello請(qǐng)求。 SayHello發(fā)送HelloRequest消息并接收HelloResponse信息:- 那么你可能要問(wèn)了,這個(gè).proto文件是如何包含在項(xiàng)目中的呢,其實(shí),如果你打開.csproject文件就會(huì)看到,通過(guò)將該文件添加到
<Protobuf>的ItemGroup中即可,如下所示:
<ItemGroup> <Protobuf Include="..\Protos\*.proto" GrpcServices="Server" /> <Content Include="@(Protobuf)" LinkBase="" /> </ItemGroup>
C#對(duì).proto文件的工具支持
工具包Grpc.Tools 被用來(lái)從.proto文件生成C#文件。生成的資產(chǎn)(文件)具有如下特性:
- 每次構(gòu)建項(xiàng)目時(shí)都會(huì)根據(jù)需要進(jìn)行生成。
- 生成的文件不會(huì)被添加到項(xiàng)目或簽入源代碼管理。
- 生成的C#文件是包含在OBJ目錄。
服務(wù)器和客戶端項(xiàng)目都需要此包。Grpc.Tools可以通過(guò)在VisualStudio中使用包管理器或添加<PackageReference>到項(xiàng)目文件:
XML復(fù)制
<PackageReference Include="Grpc.Tools" Version="1.19.0-pre1" PrivateAssets="All" />
工具包在運(yùn)行時(shí)并不是必需的,因此,應(yīng)該用PrivateAssets="All".
Services 文件夾中的具體的gRPC服務(wù)
我們知道Grpc.Tools工具包將根據(jù).proto文件的定義翻譯并生成對(duì)應(yīng)的C#類型的文件。
對(duì)于服務(wù)器端資產(chǎn),將生成一個(gè)抽象的服務(wù)基類型?;愋桶?em>.proto文件中包含的所有GRPC調(diào)用的定義。然后,您將創(chuàng)建從此基類型派生的具體服務(wù)實(shí)現(xiàn),并實(shí)現(xiàn)GRPC調(diào)用的邏輯。對(duì)于前面描述的greet.proto示例,將生成包含虛擬SayHello方法的抽象GreeterBase類型。具體的實(shí)現(xiàn)GreeterService重寫該方法并實(shí)現(xiàn)處理GRPC調(diào)用的邏輯。
正如HelloGrpc.Server項(xiàng)目中的Services\GreeterService.cs中的代碼
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply>
SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
對(duì)于客戶端,將生成一個(gè)具體的客戶端類型中的GRPC調(diào)用。.proto文件被轉(zhuǎn)換為可以調(diào)用的具體類型上的方法。為greet.proto前面描述的示例,一個(gè)具體的GreeterClient類型生成。這個(gè)GreeterClient類型包含SayHello方法,可以調(diào)用該方法來(lái)啟動(dòng)對(duì)服務(wù)器的GRPC調(diào)用。
public class Program
{
static async Task Main(string[] args)
{
// Include port of the gRPC server as an application argument
var port = args.Length > 0 ? args[0] : "50051";
var channel = new Channel("localhost:" + port, ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
await channel.ShutdownAsync();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
默認(rèn)情況下,分別生成服務(wù)器和客戶端資產(chǎn)。.proto文件包含在<Protobuf>項(xiàng)目組。若要確保僅在服務(wù)器項(xiàng)目中生成服務(wù)器資產(chǎn),GrpcServices屬性設(shè)置為Server.
XML復(fù)制
<ItemGroup> <Protobuf Include="..\Protos\*.proto" GrpcServices="Server" /> <Content Include="@(Protobuf)" LinkBase="" /> </ItemGroup>
類似地,屬性設(shè)置為Client在僅在客戶項(xiàng)目中生成。
Startup
在Startup中我們發(fā)現(xiàn)跟普通的ASP.NET Core程序有所不同,具體的如下圖所示:在ConfigureServices 服務(wù)中引入了gRPC服務(wù),然后在Configure加入了路由

而這里需要引入三個(gè)與gRPC相關(guān)的nuget包
- Grpc.AspNetCore.Server
- Google.Protobuf對(duì)于Protobuf消息API。
- Grpc.Tools
這里需要說(shuō)明的是
ASP.NET Core 中間件和功能共享路由管道,因此可以將應(yīng)用程序配置為服務(wù)其他請(qǐng)求處理程序。其他請(qǐng)求處理程序(如MVC控制器)可以與配置的GRPC服務(wù)路由并行工作。
其他需要說(shuō)明的內(nèi)容
與ASP.NET Core 接口的集成
GRPC服務(wù)可以完全訪問(wèn)ASP.NETCore功能,如依賴注入(Di)和日志功能。例如,服務(wù)實(shí)現(xiàn)可以通過(guò)構(gòu)造函數(shù)解析DI容器中的記錄器服務(wù):
public class GreeterService : Greeter.GreeterBase
{
public GreeterService(ILogger<GreeterService> logger)
{
}
}
默認(rèn)情況下,GRPC服務(wù)可以解析具有任意生存期的其他DI服務(wù)(Singleton, Scoped, or Transient)。
在GRPC方法中解析HttpContext
GRPC 應(yīng)用程序接口提供對(duì)某些HTTP/2消息數(shù)據(jù)的訪問(wèn),例如method, host, header, and trailers。訪問(wèn)是通過(guò)ServerCallContext參數(shù)傳遞給每個(gè)GRPC方法:
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply>
SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
ServerCallContext不提供對(duì)所有ASP.NET 接口中HttpContext的完全訪問(wèn)。GetHttpContext擴(kuò)展方法提供對(duì)表示ASP.NET API中底層HTTP/2消息的httpContext的完全訪問(wèn):
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request,
ServerCallContext context)
{
var httpContext = context.GetHttpContext();
return Task.FromResult(new HelloReply
{
Message = "Using https: " + httpContext.Request.IsHttps
});
}
}
請(qǐng)求體數(shù)據(jù)速率限制
默認(rèn)情況下,Kestrel服務(wù)器設(shè)置為最小請(qǐng)求主體數(shù)據(jù)速率。對(duì)于客戶端流式和雙工流式的請(qǐng)求,此速率可能不滿足,并且連接可能超時(shí)。當(dāng)GRPC服務(wù)包括客戶端流和雙工流調(diào)用時(shí),必須禁用最小請(qǐng)求正文數(shù)據(jù)速率限制:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel((context, options) =>
{
options.Limits.MinRequestBodyDataRate = null;
});
});
}
參考文章
Tutorial: Get started with gRPC in ASP.NET Core
gRPC services with ASP.NET Core
Migrating gRPC services from C-core to ASP.NET Core
總結(jié)
今天分享的內(nèi)容有點(diǎn)多,目的就是使記錄盡可能的詳細(xì),盡可能用通俗易懂的語(yǔ)言來(lái)進(jìn)行描述,讓大家能用起來(lái)。在asp.net core3.0中把grpc服務(wù)作為第一等公民進(jìn)行支持,所以我們有必要進(jìn)行下了解??赡芎芏嗯笥褧?huì)有疑問(wèn)了,我Web API用的爽歪歪,干嘛還要用gRPC這種遠(yuǎn)程過(guò)程調(diào)用協(xié)議啊。關(guān)于這個(gè)問(wèn)題,我準(zhǔn)備再單獨(dú)開一篇文章進(jìn)行講解,最后感謝大家的閱讀,碼字不易,多多推薦支持吧!
- 使用grpcui測(cè)試ASP.NET core的gRPC服務(wù)
- .NET?Core(.NET6)中g(shù)RPC使用實(shí)踐
- .Net?Core微服務(wù)rpc框架GRPC通信實(shí)際運(yùn)用
- .Net?Core微服務(wù)rpc框架GRPC通信基礎(chǔ)
- 在?ASP.NET?Core?中為?gRPC?服務(wù)添加全局異常處理
- 如何在.NET Core中為gRPC服務(wù)設(shè)計(jì)消息文件(Proto)
- .Net Core中使用Grpc的方法
- ASP.NET Core 3.0 gRPC攔截器的使用
- ASP.NET Core 3.0使用gRPC的具體方法
- ASP.NET Core中Grpc通信的簡(jiǎn)單用法
相關(guān)文章
asp.net實(shí)現(xiàn)生成靜態(tài)頁(yè)并添加鏈接的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)生成靜態(tài)頁(yè)并添加鏈接的方法,非常實(shí)用的功能,需要的朋友可以參考下2014-07-07
.NET下實(shí)現(xiàn)數(shù)字和字符相混合的驗(yàn)證碼實(shí)例
這篇文章介紹了.NET下實(shí)現(xiàn)數(shù)字和字符相混合的驗(yàn)證碼實(shí)例,有需要的朋友可以參考一下2013-11-11
一個(gè)簡(jiǎn)單的ASP.NET Forms 身份認(rèn)證的實(shí)例方法
當(dāng)訪問(wèn)默認(rèn)首頁(yè)default.aspx時(shí),會(huì)自動(dòng)跳轉(zhuǎn)到login.aspx頁(yè)面上請(qǐng)求登錄,隨便輸入用戶名和密碼,點(diǎn)擊“登錄”按鈕,會(huì)回到首頁(yè),并顯示當(dāng)前登錄的用戶名。2013-07-07
.net indexOf(String.indexOf 方法)
字符串的IndexOf()方法搜索在該字符串上是否出現(xiàn)了作為參數(shù)傳遞的字符串,如果找到字符串,則返回字符的起始位置 (0表示第一個(gè)字符,1表示第二個(gè)字符依此類推)如果說(shuō)沒(méi)有找到則返回 -12012-10-10
Asp.Net Core中創(chuàng)建多DbContext并遷移到數(shù)據(jù)庫(kù)的步驟
這篇文章主要介紹了Asp.Net Core中創(chuàng)建多DbContext并遷移到數(shù)據(jù)庫(kù)的步驟,幫助大家更好的理解和學(xué)習(xí)使用Asp.Net Core,感興趣的朋友可以了解下2021-03-03
asp.net頁(yè)面SqlCacheDependency緩存實(shí)例
這篇文章主要介紹了asp.net頁(yè)面SqlCacheDependency緩存實(shí)例,以一個(gè)完整實(shí)例來(lái)展現(xiàn)asp.net中緩存技術(shù)的使用方法,需要的朋友可以參考下2014-08-08
.NET?Framework?的項(xiàng)目如何使用?FTP?下載文件
本文專門針對(duì)面向?.NET?Framework?的項(xiàng)目,?對(duì)于面向?.NET?6?及更高版本的項(xiàng)目,不再支持?FTP,此示例演示如何從?FTP?服務(wù)器下載文件,感興趣的朋友跟隨小編一起看看吧2024-01-01
.Net Core 中選項(xiàng)Options的具體實(shí)現(xiàn)
這篇文章主要介紹了.Net Core 中選項(xiàng)Options的具體實(shí)現(xiàn),文中運(yùn)用大量代碼對(duì)相關(guān)知識(shí)詳細(xì)介紹,感興趣的小伙伴可以參考一下這篇文章,希望對(duì)你有所幫助2021-09-09

