文章目錄
使用 GenericHost 來 Host gRPC Server
之前筆記 在 .NET Core console 上使用 Dependency Injection - DI 提到 ASP.NET Core 有兩種 host 方式:
- WebHost
- Generic Host
而在之前另一則筆記 使用 ASP.NET Core 2.2 來 Host gRPC Server 使用到 WebHost 來 host gRPC Server,經同事提醒其實不需要用到 kestrel 來處理 request,覺得相當有道理於是我就來改版了
基本環境說明
- macOS Mojave 10.14.5
- .NET Core SDK 2.2.107 (.NET Core Runtime 2.2.5)
- 使用之前筆記 使用 ASP.NET Core 2.2 來 Host gRPC Server 作為基礎來修改
NuGet package
- Microsoft.AspNetCore 2.2.0
- Microsoft.Extensions.Hosting 2.2.0
修改步驟
- 建立 .NET Core console 專案
安裝 NuGet package
- Microsoft.AspNetCore 2.2.0
- Microsoft.Extensions.Hosting 2.2.0
將
gRPC.Message
專案加入參考複製
gRPCServiceImpl.CS
public class gRPCServiceImpl : gRPCService.gRPCServiceBase { public override Task<Response> SayHello(HelloRequest request, ServerCallContext context) { return Task.FromResult(new Response { IsSuccess = true, ResponseMsg = $"Hi {request.Name} @ {request.SendDate.ToDateTime()} !!!" } ); } public override Task<Response> SayGoodbye(GoodByeRequest request, ServerCallContext context) { return Task.FromResult(new Response { IsSuccess = true, ResponseMsg = $"Bye,{request.Name}" } ); } }
建立
gRPCServer.cs
用來啟動 gRPC Serverpublic class gRPCServer { public string Host { get; private set; } public int Port { get; private set; } private readonly Grpc.Core.Server serverInstance; public gRPCServer(string host, int port, params ServerServiceDefinition[] serverServices) { Host = host; Port = port; serverInstance = new Grpc.Core.Server //( // // channel 設定請自行依專案狀況調整 // new List<ChannelOption> // { // new ChannelOption("grpc.keepalive_permit_without_calls", 1), // new ChannelOption("grpc.http2.max_pings_without_data", 0) // } // ) { Ports = { new ServerPort(Host, Port, ServerCredentials.Insecure) } }; foreach (var serverService in serverServices) { serverInstance.Services.Add(serverService); } serverInstance.Start(); } }
註冊並啟動 gRPC
static async Task Main(string[] args) { var builder = new HostBuilder() .ConfigureAppConfiguration((hostingContext, config) => { //沒有 appsettings.json 就可以不用加 //config.AddJsonFile("appsettings.json", optional: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureServices((hostContext, services) => { services.AddOptions(); var host = "127.0.0.1"; var port = 50051; services.AddSingleton<gRPCService.gRPCServiceBase, gRPCServiceImpl>(); var Services = services.BuildServiceProvider(); services.AddSingleton( new gRPCServer(host, port, gRPCService.BindService(Services.GetRequiredService<gRPCService.gRPCServiceBase>()) )); }); await builder.RunConsoleAsync(); }
加入 Jaeger tracer (optional)
ILoggerFactory loggerFactory = new LoggerFactory().AddConsole(); var serviceName = "gRPCServerOnGenericHost"; Tracer tracer = TracingHelper.InitTracer(serviceName, loggerFactory); ServerTracingInterceptor tracingInterceptor = new ServerTracingInterceptor(tracer); services.AddSingleton( new gRPCServer(host, port, gRPCService.BindService(Services.GetRequiredService<gRPCService.gRPCServiceBase>()) .Intercept(tracingInterceptor) ));
心得
Generic Host 適合用來 host 不需處理 http request 的應用程式,以 gRPC Server 而言是相當適合,再次由衷地佩服起同事,深深覺得有強大的同事一起工作真的可以學到很多
回到 ASP.NET Core host gRPC 的主題上,我翻了 Grpc.AspNetCore.Server
的原始碼,目前看來主要功能都是使用 WebHost,其中有一部份功能還包含了處理 http request。因此屆時使用 .NET Core 3 ,是不是可以簡單的 migrate 過去可能還需要持續觀察,但 .NET Core 3 還未正式上市,Grpc.AspNetCore.Server
也還在 preview,日後會不會調整加入 Generic Host 支援就拭目以待囉
詳細程式碼請參考 yowko/generichostgrpc
參考資訊
文章作者 Yowko Tsai
上次更新 2021-11-02
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。