17

我使用Link中给出的示例在 C# 中创建了一个 GRPC 服务器。现在我想弄清楚我应该如何托管这个服务器,以便实现以下目标:

  • 我应该将此服务器设为控制台应用程序还是 Windows 服务。如果我将其设为 Windows 服务,那么更新服务将会很麻烦(这是一个很大的负面影响),如果我将其设为控制台应用程序,那么更新将只需要关闭 exe。但这伴随着错误地关闭相同的价格。还有其他更好的方法吗?
  • 有了 IIS,这个问题就不会出现,因为我可以简单地从 LB 中删除该站点并停止该网站以执行更新,但由于 GRPC 不会成为 IIS 的一部分,我不确定如何才能使其正常工作。

欢迎任何关于更好架构的参考。

4

4 回答 4

20

我们可以使用Microsoft.Extensions.Hostingpacakge 来托管 .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 来进行一些清理。

HostBuilder中的其他配置可以看这篇博客

于 2018-03-27T02:59:28.997 回答
4

我要再添加一个选项。

使用 dot net core,您现在可以将其作为 Linux 守护程序运行。

于 2017-06-04T17:33:24.853 回答
3

目前 gRPC 不支持与 ASP.Net/IIS 的集成。您需要将服务器托管在控制台中或作为 Windows 服务。

您可能希望这是一项 Windows 服务,以便更轻松地保持服务器在重新启动或崩溃时运行。如果您想轻松地将控制台应用程序转换为 Windows 服务,我建议您使用出色的TopShelf Nuget。

可以像更新控制台应用程序一样更新服务。

  • 停止 Windows 服务。net stop <service-name}>
  • 复制更新的程序集。
  • 启动 Windows 服务net start <service-name>
于 2016-03-01T17:52:00.140 回答
3

我的公司(Shortbar)正在为 gRPC 上名为 HOLMS 的酒店管理系统构建应用程序服务器。我们的设置如下:

  • HOLMS.Application 是一个执行服务器实际工作的 .NET 类库(程序集)
  • HOLMS.Application.ConsoleRunner 是托管 HOLMS.Application 的 C# 控制台应用程序。控制台运行器由 (1) 开发人员为了方便(在问题中提到)以及 (2) 在 Docker 容器内运行的生产场景使用,其中容器运行时(例如 Amazon ECS)实现作业控制/缩放。它遵循“12 因素应用程序”指南,包括将自身作为单个、独立、无状态的进程运行、快速启动/关闭和环境变量配置注入。系统记录到标准输出,标准输出被耗尽,但标准输出在 prod 环境(例如 Sumo、logstash 等)中被耗尽。这就是我们的 SaaS 多租户解决方案投入生产的方式。
  • HOLMS.Application.ServiceRunner 将 HOLMS.Application 打包到 Windows 服务中,适用于客户的 IT 组将自行运行服务的更传统的内部部署情况。此软件包使用 Windows 注册表进行配置,并依赖 Windows 服务作业控制进行启动/关闭/重新启动。它记录到 Windows 事件日志。

ConsoleRunner 和 ServiceRunner 各只有 200 行左右的代码;大多数情况下,他们只是包装应用程序包,然后调用它。

希望这可以帮助。

于 2016-07-15T21:00:58.073 回答