我正在尝试使Grpc服务器作为控制台守护程序运行。此gRPC服务器是在Docker容器中运行的微服务。

我可以找到的所有示例都利用以下内容:

Console.ReadKey();

实际上,这确实会阻塞主线程并使它保持运行,但是在docker中不起作用,并出现以下错误:
"Cannot read keys when either application does not have a console or when console input has been redirected. Try Console.Read."

现在,我可能可以尝试专门为docker找到一种解决方法,但这仍然感觉不对。有谁知道保持生产运行良好的“生产就绪”方法?

最佳答案

现在,您可以使用Microsoft.Extensions.Hosting pacakge,它是asp.net核心和控制台应用程序的宿主和启动基础结构。

与asp.net核心一样,您可以使用HostBuilder API开始构建gRPC主机并进行设置。以下代码用于获取一直运行直到停止的控制台应用程序(例如,使用Control-C):

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;

public class Program
{
    public static async Task Main(string[] args)
    {
        var hostBuilder = new HostBuilder();

         // register your configuration and services.
        ....

        await hostBuilder.RunConsoleAsync();
    }
}

为了运行gRPC服务,您需要在托管服务中启动/停止Grpc.Core.Server。托管服务基本上是一段代码,它在主机本身启动时由主机运行,而在主机停止时相同。这在IHostedService接口(interface)中表示。也就是说,实现GrpcHostedService来覆盖接口(interface):
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();
    }
}

真的很简单。我们通过依赖项注入(inject)获得了一个GrpcHostedService实例,并在主机启动时对其运行StartAsync。当主机停止时,我们运行StopAsync,以便我们可以正常关闭所有内容,包括Grpc服务器。

然后返回Program.cs并进行一些更改:
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中的其他配置,您可以看到此blog

关于c# - 保持Dotnet Core Grpc Server作为控制台应用程序运行?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45989148/

10-16 10:39