Изящно завершите работу общего хоста в демоне Linux .NET Core 2 - PullRequest
0 голосов
/ 23 апреля 2019

Я совершенно новичок как в .NET Core, так и в разработке демонов linux. Я прошел через пару похожих вопросов, таких как Изящное убийство демона .NET Core, работающего в Linux или Изящное завершение работы с помощью Generic Host в .NET Core 2.1 , но они не решили моя проблема.

Я создал очень простое консольное приложение в качестве теста с использованием размещенной службы. Я хочу, чтобы он работал как демон, но у меня проблемы с его корректным завершением. Когда он запускается из консоли как в Windows, так и в Linux, все работает нормально.

public static async Task Main(string[] args)
{
    try
    {
        Console.WriteLine("Starting");

        var host = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<DaemonService>();
            });

        System.IO.File.WriteAllText("/path-to-app/_main.txt", "Line 1");
        await host.RunConsoleAsync();
        System.IO.File.WriteAllText("/path-to-app/_main.txt", "Line 2");
    }
    finally
    {
        System.IO.File.WriteAllText("/path-to-app/_main-finally.txt", "Line 1");
    }
}

public class DaemonService : IHostedService, IDisposable
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        System.IO.File.WriteAllText("/path-to-app/_Start.txt", "Line 1");

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        System.IO.File.WriteAllText("/path-to-app/_Stop.txt", "Line 1");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        System.IO.File.WriteAllText("/path-to-app/_Dispose.txt", "Line 1");
    }
}

Если я запускаю приложение из консоли, все работает как положено. Однако, когда он работает как демон, после выполнения либо kill <pid>, либо systemctl stop <service>, выполняются методы StopAsync и Dispose, но не более того: ни in Main после await, ни finally блок.

Примечание: я не использую ничего из ASP.NET Core. AFAIK это не обязательно для того, что я делаю.

Я что-то не так делаю? Это ожидаемое поведение?

1 Ответ

0 голосов
/ 24 апреля 2019

Подводя итог разговора ниже исходного вопроса.

Похоже, что IHostedService используется в HostBuilder, это то, что контролирует SIGTERM. Как только Task помечен как завершенный, он определяет, что служба корректно завершила работу. Перемещая System.IO.File.WriteAllText("/path-to-app/_main.txt", "Line 2"); и код в блоке finally внутри области службы, это можно было исправить. Измененный код предоставлен ниже.

public static async Task Main(string[] args)
{
    Console.WriteLine("Starting");

    var host = new HostBuilder()
        .ConfigureServices((hostContext, services) =>
        {
           services.AddHostedService<DaemonService>();
        });

    System.IO.File.WriteAllText("/path-to-app/_main.txt", "Line 1");
    await host.RunConsoleAsync();
}
public class DaemonService : IHostedService, IDisposable
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        System.IO.File.WriteAllText("/path-to-app/_Start.txt", "Line 1");

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
            return Task.CompletedTask;
    }

    public void Dispose()
    {
        try
        {
            System.IO.File.WriteAllText("/path-to-app/_Dispose.txt", "Line 1");
            System.IO.File.WriteAllText("/path-to-app/_Stop.txt", "Line 1");
        }
        finally
        {
            System.IO.File.WriteAllText("/path-to-app/_main-finally.txt", "Line 1");
        }
    }
}

Поскольку это работает как служба, мы пришли к выводу, что на самом деле имеет смысл содержать завершение самой службы в этой области, аналогично тому, как работают приложения ASP.NET Core, предоставляя только службу внутри Program.cs файл и позволяет самой службе поддерживать свои зависимости.

Я бы посоветовал содержать как можно больше в сервисе и просто запустить метод Main.

...