gpt4 book ai didi

.net-core - .NET 核心 BackgroundService 没有作为守护进程正常关闭

转载 作者:行者123 更新时间:2023-12-04 09:55:09 28 4
gpt4 key购买 nike

我正在开发 .NET Core 3.1 后台服务,该服务将作为守护进程安装在 Debian AWS EC2 实例上。
优雅地关闭守护进程以停止运行任务并完成一些要处理的任务(发送一些事件等)是很重要的。基本实现如下所示:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace MyApp.WorkerService
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).UseSystemd().Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
}

你可以看到我在这里使用了 SystemdLifetime

worker 如下:

using System;
using System.Threading;
using System.Threading.Tasks;
using AdClassifier.App.Audit;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NLog;

namespace MyApp.WorkerService
{
public class Worker : BackgroundService
{
private static readonly ILogger Logger = LogManager.GetLogger(typeof(Worker).FullName);

private readonly int _jobPollIntervalMilliseconds;

public IServiceProvider Services { get; }

public Worker(IServiceProvider services, IConfiguration configuration)
{
Services = services;
_jobPollIntervalMilliseconds = configuration.GetValue<int>("JobPollIntervalMilliseconds");
}

protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Logger.Info("Worker running.");
var task = new Task(o => DoWork(stoppingToken), stoppingToken);
task.Start();
return task;
}

public override async Task StopAsync(CancellationToken cancellationToken)
{
Logger.Info("Worker stopping");
await base.StopAsync(cancellationToken);
Logger.Info("Worker stopped");
}

private void DoWork(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = Services.CreateScope())
{
// do some work
}

Thread.Sleep(_jobPollIntervalMilliseconds);
}
Logger.Info("cancellation requested!");
}
}
}

问题
正如我提到的,我们将其设置为守护进程,如下所示

[Unit]
Description=my worker
Requires=deploy-my-worker.service
After=multi-user.target deploy-my-worker.service
ConditionFileIsExecutable=/home/my-worker/current/myworker
[Service]
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=DOTNET_CLI_TELEMETRY_OPTOUT=true
Environment=ASPNETCORE_URLS=http://*:5000
Environment=DOTNET_ENVIRONMENT=Staging
Environment=ASPNETCORE_ENVIRONMENT=Staging
WorkingDirectory=/home/my-worker/current
ExecStart=/home/my-worker/current/myworker
SyslogIdentifier=my-worker
Restart=always
RestartSec=10
KillSignal=SIGTERM
User=usr
Group=usrgroup
[Install]
WantedBy=multi-user.target

问题是 worker 不会优雅地停止。我正在检查以下日志条目的日志,但它们没有出现:
Worker 停止取消请求!Worker 停止
请注意,该应用程序确实关闭了。我们为关闭服务所做的尝试如下:

  • 关闭服务器
  • systemctl 停止 my-worker.service
  • 杀死
  • kill -SIGTERM
  • kill -SIGINT

什么有效

如果我这样启动 worker:usr@ip-10-168-19-126:~/my-worker/current$ ./myworker 然后按 Ctrl-C (应该是 SIGINT),应用程序停止,在我的日志中我可以看到正确的消息:

2020-05-21 16:16:57.9676|INFO|MyApp.WorkerService.Worker|Worker stopping 
2020-05-21 16:16:57.9937|INFO|MyApp.WorkerService.Worker|cancellation requested!
2020-05-21 16:16:57.9937|INFO|MyApp.WorkerService.Worker|Worker stopped
2020-05-21 16:16:57.9980 Info AppDomain Shutting down. Logger closing...

关于如何让守护进程按预期工作的任何想法?

注意:
我有充分的理由相信问题出在守护程序设置或 UseSystemd() 的某个地方。
我将 UseSystemd() 替换为 UseWindowsService() 并将其作为 Windows 服务安装在 Windows 机器上。然后继续通过“服务”面板启动和停止服务,并按预期看到关闭日志记录。
因此,我很想假设在实现中没有问题,而是在设置中的某个地方。

最佳答案

看来问题出在 NLog 的关闭上。这是通过执行以下操作修复的:LogManager.AutoShutdown = false; 并在 Worker::StopAsync 中添加 LogManager.Shutdown();

关于.net-core - .NET 核心 BackgroundService 没有作为守护进程正常关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61936664/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com