gpt4 book ai didi

c# - .NET Core 3.1 - Linux 容器 : Clean Shutdown 中的 Worker 服务

转载 作者:行者123 更新时间:2023-12-04 17:21:44 24 4
gpt4 key购买 nike

下面是 Visual Studio 2019 中用于创建辅助服务的基本模板的代码。将此服务部署到 linux 容器时,当容器被请求停止时,ExecuteAsync 方法中的代码 CancellationToken 永远不会被取消。在以各种方式停止容器后,我又看到 10 个“Worker running at”日志条目,然后容器停止了。这与我读到的一致:docker 发送一个 SIGTERM 命令,等待 10 秒,然后如果容器没有自行停止则发送一个 SIGKILL 命令。

我正在寻找的是当容器被请求停止时 CancellationToken 应该如何设置为 Canceled 的答案?我的最终目标是确保在容器突然停止之前完成或回滚所有运行中的事务以及其他此类清理工作。

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

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


public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;

public Worker(ILogger<Worker> logger)
{
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}

我已经尝试订阅 AppDomain.CurrentDomain.ProcessExit 事件,因为这似乎是网络上大多数人所说的(没有任何示例),但要么我实现它的方式不起作用,要么就是这样'正确的做法。从 VS2019 运行容器,永远不会执行事件处理程序的代码。以下是我尝试实现的方式:

public static void Main(string[] args)
{
using (CancellationTokenSource cts = new CancellationTokenSource())
{
AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) =>
{
cts.Cancel();
};

var host = CreateHostBuilder(args).Build();
Task task;

task = host.RunAsync(cts.Token);

task.Wait(cts.Token);
}
}

更新:我猜这个问题与模板构建 docker 文件和启动容器的方式有关。 SIGTERM 被发送到 PID 1 并查看容器上 ps -ef 的结果,tail 的调用是 PID 1 而不是 .netcore 解决方案中的任何内容.我想下一个问题是如何解决这个问题? ps -ef results

更新(请求的 Docker 文件)docker 文件是 Visual Studio 为此模板创建的默认 docker 文件。

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["WorkerService2/WorkerService2.csproj", "WorkerService2/"]
RUN dotnet restore "WorkerService2/WorkerService2.csproj"
COPY . .
WORKDIR "/src/WorkerService2"
RUN dotnet build "WorkerService2.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WorkerService2.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WorkerService2.dll"]

最佳答案

这实际上是在调试时从 Docker for Windows 中的 Visual Studio 运行容器时出现的问题(我猜 Docker for Mac 会类似)。

通过昨晚生成的 dockerfile 中的这个链接(https://aka.ms/containerfastmode),当从 Visual Studio 运行图像进行测试时,入口点将不是 netcore 应用程序,因此 PID1 将不是 .netcore应用程序,它不会收到 SIGTERM 信号。但是,.netcore 应用程序应该是未通过 Visual Studio 启动时的入口点。

The entry point is tail -f /dev/null, which is an infinite wait tokeep the container running. When the app is launched through thedebugger, it is the debugger that is responsible to run the app (thatis, dotnet webapp.dll). If launched without debugging, the toolingruns a docker exec -i {containerId} dotnet webapp.dll to run the app.

在 Visual Studio 中完成构建后,我直接从 Docker for Windows 为我的应用程序测试了带有 :latest 标记的图像。当我这样做时,使用了 dockerfile 中的 ENTRYPOINT 并且 PID 1 是预期的 .netcore 应用程序。停止容器后,将触发 CancellationToken.Cancel() 并抛出 OperationCancelledException。

下面是模板的基本代码,我以后会使用它来解释 CancellationToken 被取消并在取消时抛出异常。

{
try
{
_logger.LogInformation($"WORKER STARTING at: {DateTimeOffset.Now}");

while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("$Worker running at: {DateTimeOffset.Now}");
await Task.Delay(1000, stoppingToken);
}

_logger.LogInformation($"Exited While Loop: {DateTimeOffset.Now} (Will never get hit as is)");
}
catch(OperationCanceledException)
{
_logger.LogInformation("!!!OperationCancelled!!! Start clean up from here");
}
catch(Exception ex)
{
_logger.LogCritical(ex, $"Exception Caught: {ex.GetType().FullName}");
}

_logger.LogInformation($"WORKER STOPPING at: {DateTimeOffset.Now}");
}

关于c# - .NET Core 3.1 - Linux 容器 : Clean Shutdown 中的 Worker 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65723379/

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