应如何托管 GRPC 服务
本文关键字:服务 GRPC 何托管 | 更新日期: 2023-09-27 18:32:58
我使用链接中给出的示例在C#中创建了一个GRPC服务器。现在我想弄清楚我应该如何托管此服务器,以便实现以下目标:
- 我应该将此服务器设置为控制台应用程序还是Windows服务。如果我将其设为 Windows 服务,那么更新该服务将很麻烦(这是一个很大的负面影响(,如果我将其设为控制台应用程序,那么更新只需要关闭 exe。但随之而来的是错误关闭相同的代价。还有其他更好的方法吗? 使用IIS,
- 此问题不会在那里,因为我可以简单地从LB中删除站点并停止该网站以执行更新,但是由于GRPC不会成为IIS的一部分,因此我不确定有什么方法可以使其工作。
欢迎任何有关更好架构的参考。
我们可以使用 Microsoft.Extensions.Hosting
pacakge 来托管 .net 核心控制台应用程序,方法是使用 HostBuilder API 开始构建 gRPC 主机并进行设置。
为了运行 gRPC 服务,我们首先需要在托管服务中启动/停止Grpc.Core.Server
。托管服务基本上是一段代码,在主机本身启动时由主机运行,在主机停止时也是如此。以下代码实现一个GrpcHostedService
来重写IHostedService
接口:
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Microsoft.Extensions.Hosting;
namespace Grpc.Host
{
public class GrpcHostedService: IHostedService
{
private Server _server;
public GrpcHostedService(Server server)
{
_server = server;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_server.Start();
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken) => await _server.ShutdownAsync();
}
}
在Program.cs
中,使用 HostBuilder API 开始构建我们的 grpc 主机并对其进行设置:
public class Program
{
public static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder()
// Add configuration, logging, ...
.ConfigureServices((hostContext, services) =>
{
// Better to use Dependency Injection for GreeterImpl
Server server = new Server
{
Services = {Greeter.BindService(new GreeterImpl())},
Ports = {new ServerPort("localhost", 5000, ServerCredentials.Insecure)}
};
services.AddSingleton<Server>(server);
services.AddSingleton<IHostedService, GrpcHostedService>();
});
await hostBuilder.RunConsoleAsync();
}
}
通过这样做,通用主机将自动在我们的托管服务上运行 StartAsync,而该服务又会在Server
实例上调用 StartAsync,实质上是启动 gRPC 服务器。
当我们使用 Control-C 关闭主机时,通用主机将自动在我们的托管服务上调用 StopAsync,这将再次在Server
实例上调用 StopAsync,这将执行一些清理。
有关主机生成器中的其他配置,您可以查看此博客。
我将再添加一个选项。
使用dot net core,您现在可以将其作为Linux守护程序运行。
目前 gRPC 不支持与 ASP.Net/IIS 集成。您需要在控制台中或作为 Windows 服务托管服务器。
您可能希望这是一项 Windows 服务,以便更轻松地在重新启动或崩溃时保持服务器运行。如果你想轻松地将控制台应用程序变成Windows服务,我建议使用优秀的TopShelf Nuget。
可以像更新控制台应用一样更新服务。
- 停止 Windows 服务。
net stop <service-name}>
- 复制更新的程序集。
- 启动 Windowsservice
net start <service-name>
我的公司(Shortbar(正在为 gRPC 上的一个名为 HOLMS 的酒店管理系统构建应用程序服务器。我们的设置如下:
- 霍尔姆斯。应用程序是一个 .NET 类库(程序集(,用于执行服务器的实际工作
- 霍尔姆斯。Application.ConsoleRunner 是一个托管 HOLMS 的 C# 控制台应用程序。应用。控制台运行器由 (1( 开发人员使用以方便(在问题中提到(以及 (2( 在 Docker 容器内运行的生产场景,其中容器运行时(例如 Amazon ECS(实现作业控制/扩展。它遵循"12 因素应用"准则,包括将自身作为单个、独立、无状态的进程运行、快速启动/关闭和环境变量配置注入。系统记录到标准输出,该标准输出被清空,但在生产环境中(例如相扑,日志等(中排出。这就是我们的 SaaS 多租户解决方案将如何投入生产。
- 霍尔姆斯。Application.ServiceRunner 包 HOLMS。应用程序到 Windows 服务中,适用于更传统的本地情况,其中客户的 IT 组将自行运行服务。此程序包使用 Windows 注册表进行配置,并依赖于 Windows 服务作业控制进行启动/关闭/重新启动。它记录到 Windows 事件日志中。
ConsoleRunner 和 ServiceRunner 每个只有大约 200 行代码;在大多数情况下,它们只是包装应用程序包,然后调用它。
希望这有帮助。