首页 > 解决方案 > 如何编写计划/触发/按需 webjob 控制台应用程序以检测关闭,以便可以优雅地处理它?

问题描述

我正在将现有的 c# .net 应用程序作为触发(按需,而不是使用队列/触发器/函数连续)网络作业运行。有时运行时间很长,比如 30 多分钟。效果很好。

[已编辑] 如果我尝试停止 webjob,通过在我的应用程序服务的应用程序设置中将 WEBJOBS_STOPPED 设置为 1,那么如果 Azure/Kudu 没有正常检测到关闭并及时终止,则 webjob 将被 Azure/Kudu 中止(5秒?30 秒?)

我已经尝试使用 WebJobsShutdownWatcher() 作为几个示例说明,并且正如 Joey 指出的那样,但它仍然没有检测到关闭,并且 Azure/Kudu 无论如何都会中止它。我什至手动编写了检查关闭文件是否存在的代码(请参阅 GitHub 中的 WebJobsShutdownWatcher() 代码),但该文件似乎没有为我的触发/按需网络作业创建,因此我的代码什么也没检测到。

我最初的问题是:WebJobsShutdownWatcher() 是否适用于 Triggered(OnDemand) 网络作业?还是仅适用于连续网络作业?我怀疑 WebJobsShutdownWatcher 只适用于 Continuous webjobs,所以在我花更多时间尝试调试它之前,我想在这里问一下。

我认为乔伊的回答有效,但我自欺欺人,因为控制台应用程序似乎因关闭而终止,但我现在认为它终止是因为我没有正确编码。无论如何,即使使用 .Register() 或检查 .Token.IsCancellationRequested,我的控制台应用程序似乎也没有收到通知,因此一旦我将 WEBJOBS_STOPPED 设置为 1,Azure/Kudu 就会中止它。

所以我开始想,也许还有其他 Azure 代码我必须添加到我的简单控制台应用程序中,我不知道,比如 JobHost 初始化和 host.RunAndBlock() 或类似的东西,让 Azure 做这件事并触发我使用 .Register 注册的匿名函数,或设置 .Token.IsCancellationRequested 标志。

我已经包含了我的整个简单测试程序,欢迎所有建议,尽管我会说我希望对我的 vanilla .NET 控制台应用程序进行最小的更改,我真的不想创建比我必须做的更多的东西,比如 JobHost (),或者触发了我必须在 Azure 中配置才能触发的功能。只是一个简单的控制台应用程序,带有一个带有 cron 计划的 settings.job,它运行和停止、运行和停止,如果它检测到 webjob 关闭,则提前终止以避免 Azure/Kudu 中止。

class Program
{
    static Boolean runFlag1 = true;
    static Boolean runFlag2 = true;
    static void Main(string[] args)
    {
        var watcher = new WebJobsShutdownWatcher();
        var cancellationToken = watcher.Token;
        cancellationToken.Register(() =>
        {
            Console.WriteLine("Webjob Shutdown signaled.");
            runFlag1 = false;
        });

        var t = Task.Run(() =>
        {
            Console.WriteLine("Beginning webjob loop...");
            while (runFlag1 && runFlag2)
            {
                Thread.Sleep(1000);
                Thread.Yield();

                if (watcher.Token.IsCancellationRequested)
                {
                    Console.WriteLine("");
                    Console.WriteLine("Webjob IsCancellationRequested=true");
                    runFlag2 = false;
                }
            }
            Console.WriteLine("");
            Console.WriteLine("Ending webjob loop, runFlag1={0} runFlag2={1}", runFlag1, runFlag2);
        });
        t.Wait();

        Console.WriteLine("Exited Task. runFlag1={0} runFlag2={1}", runFlag1, runFlag2);
    }
}

谢谢,博

标签: c#.netazureapplication-shutdownazure-webjobs-triggered

解决方案


是的,您可以使用WebJobsShutdownWatcher该类,因为它具有Register在取消标记被取消时调用的函数,换句话说,当 web 作业停止时。

var cancellationToken = new WebJobsShutdownWatcher().Token;
cancellationToken.Register(() =>
{
    Console.Out.WriteLine("Do whatever you want before the webjob is stopped...");
});

如果您使用触发函数,则可以将CancellationToken参数添加到函数签名中。当主机自动关闭时,运行时将取消该令牌,从而允许您的函数接收通知。这是您可以参考的线程。

public static void QueueFunction(
        [QueueTrigger("QueueName")] string message,
        CancellationToken cancellationToken)
{
    if(cancellationToken.IsCancellationRequested) return;
    ...
}

推荐阅读