Worker服务容器完成后,如何停止它



我有一个.Net Worker服务,它作为K8S Cronjob运行,但当它运行到完成时,该服务并没有按预期退出。吊舱仍处于运行状态,因此K8S作业从未完成,如以下日志所示:

[40m[1m[33mwarn[39m[22m[49m: UploaderCron.Worker[0]
Worker STARTING
[40m[32minfo[39m[22m[49m: UploaderCron.Worker[0]
Worker running at: 11/04/2022 11:27:01 +00:00
Connected to SFTP Server
/taat/DEV-AAA-20221104T112701/DatabaseA20221104112606.gz
File uploaded successfully
/taat/DEV-BBB-20221104T112701/DatabaseB20221104112606.gz
File uploaded successfully
....
....
Backup file successfully purged
Backup file successfully purged
[40m[32minfo[39m[22m[49m: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
[40m[32minfo[39m[22m[49m: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
[40m[32minfo[39m[22m[49m: Microsoft.Hosting.Lifetime[0]
Content root path: /app
[40m[32minfo[39m[22m[49m: UploaderCron.Worker[0]
Worker running at: 11/04/2022 11:35:46 +00:00
Connected to SFTP Server
[40m[32minfo[39m[22m[49m: UploaderCron.Worker[0]
Worker running at: 11/04/2022 11:44:08 +00:00
Connected to SFTP Server
[40m[32minfo[39m[22m[49m: UploaderCron.Worker[0]
Worker running at: 11/04/2022 11:52:31 +00:00
Connected to SFTP Server

预期

  1. 辅助服务应在K8S清单中指定的特定时间每天运行(直到完成(
  2. 辅助服务应仅将连接到SFTP服务器一次,并执行所有必需的操作(上载(直至完成所谓执行,我的意思是上传目录应该创建一次,而且只能创建一次
  3. 任务完成后,容器应停止
  4. 容器停止后,相应的pod/cronjob应更改为Completed状态

实际

  1. 辅助服务运行完成,即创建上传目录并上传所有相关文件
  2. 在中指定的时间过后,辅助服务将再次运行
    await Task.Delay(450000, stoppingToken);
    

在每种情况下,服务都会再次连接到sftp服务器并创建上传目录(这次没有上传文件,只创建目录(。

  1. 辅助服务pod保持运行状态,容器日志显示这一行从未被调用:
_logger.LogWarning("Worker STOPPING: {time}", DateTimeOffset.Now);

这是我的工人代码:

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 Helper.LoadFiles();    
await Task.Delay(450000, stoppingToken);
}
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogWarning("Worker STARTING");
return base.StartAsync(cancellationToken);
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogWarning("Worker STOPPING: {time}", DateTimeOffset.Now);
return base.StopAsync(cancellationToken);
}
}

Helper.cs

public static class Helper
{
public static async Task UploadFiles()
{  
using (var fileStream = System.IO.File.OpenRead(localFilePath))
{
sftp.UploadFile(fileStream, remoteFilepath);
Console.WriteLine("File uploaded successfully");               
}               
//more upload logic 
}
public static async Task LoadFiles()
{   
await Helper.UploadFiles();   
}
}

工人服务的K8S CronJob(容器上传器(:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: dbbackup
spec:
schedule: "26 11 * * *" #Cron job everyday at 11:26am
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: 
matchLabels:
app.kubernetes.io/name: mongodb
topologyKey: "kubernetes.io/hostname"
initContainers:
- name: backup
image: backup:latest
imagePullPolicy: "IfNotPresent"
volumeMounts:
- mountPath: /tmp
name:  datadir
command: ['sh', '-c',"./dump.sh"]
containers:
- name: uploader
image: uploader:latest
imagePullPolicy: "IfNotPresent"
volumeMounts:
- mountPath: /tmp
name:  datadir
restartPolicy: OnFailure
volumes:
- name: datadir
persistentVolumeClaim:
claimName: mongodb-taat

注意:就上下文而言,我遵循这里给出的参考实现

我缺少什么,以便在任务完成后容器停止?

好吧,就在这里,您的后台服务一直在故意运行,直到被要求停止,定期执行其工作:

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

如果您希望应用程序在完成时退出,那么只需执行以下操作:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Helper.LoadFiles();
}
finally
{
_hostApplicationLifetime.StopApplication();
}
}
private readonly IHostApplicationLifetime _hostApplicationLifetime;
public Worker(ILogger<Worker> logger, IHostApplicationLifetime hostApplicationLifetime)
{
_logger = logger;
_hostApplicationLifetime = hostApplicationLifetime;
}

最新更新