正常关闭Azure WebJobs [英] Graceful Shutdown of Azure WebJobs

查看:92
本文介绍了正常关闭Azure WebJobs的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我计划使用连续的Azure WebJob发送电子邮件和推送通知.我知道WebJobs会由于各种原因不时启动和停止.很好,但是我想有机会在关闭工作之前进行清理".

I'm planning to use a continuous Azure WebJob to send emails and push notifications. I understand that WebJobs will be started and stopped from time to time for various reasons. That's fine, but I would like to have the opportunity to "clean up" prior to the job getting shut down.

这样,我的WebJob可以更新数据库记录的状态或删除每个批处理中已处理的队列项目,这样下次作业运行时就不会发送重复的消息.

That way my WebJob can update the status of database records or delete queue items that have already been processed in each batch so duplicate messages won't get sent the next time the job runs.

在黑暗中拍摄时,我尝试将以下代码添加到C#控制台应用程序中:

As a shot on the dark, I tried adding the following code to my C# console application:

Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
{
  e.Cancel = true;
  program.keepRunning = false;
};

然后,我使用keepRunning布尔控件来控制主while循环,并将Console.Writeline(优雅退出")置于while循环之外.但这似乎没有帮助.当我告诉作业停止(使用Azure网站的Webjobs选项卡上的停止"按钮)时,该作业将从列表中消失,并显示无法停止作业:'JobName'".在Azure门户中(在页面底部).我在WebJob的日志中看不到优雅退出"文本.所以我删除了该代码,因为它没有帮助.

And then I used the keepRunning bool to control the main while loop, and put a Console.Writeline("Exited Gracefully") outside of the while loop. But that didn't seem to help. When I tell the job to stop (using the stop button from the Webjobs tab of my Azure Website), the job disappears from the list and it says "Could not stop job: 'JobName'." in the Azure portal (at the bottom of the page). I don't see the "Exited Gracefully" text in the WebJob's log. So I took that code out since it wasn't helping.

所以,我正在寻找一种通知WebJob的好方法,通知它的秒数已编号,并且需要按顺序处理事务.

So, I'm looking for a good way for my WebJob to be notified that its seconds are numbered and that it needs to get its affairs in order.

推荐答案

根据他自己的博客文章,我相信在阿米特最后回答之后不久,情况就发生了变化:

I believe things changed soon after Amit answered last, according to his own blog post in fact here: WebJobs Graceful Shutdown

观看此视频 6:00+以后不久,对此进行了一些讨论.

Also see this video a little after the 6:00+ mark for some discussion on this.

来自阿米特(Amit)的博客:

From Amit's blog:

Azure通知即将停止的进程的方式是 将文件放置(创建)在作为环境传递的路径上 变量名为WEBJOBS_SHUTDOWN_FILE.

The way Azure notifies the process it's about to be stopped is by placing (creating) a file at a path that is passed as an environment variable called WEBJOBS_SHUTDOWN_FILE.

任何要监听关闭通知的WebJob都会 实际上必须检查文件的存在(使用简单 File.Exists函数或在任何脚本中使用FileSystemWatcher (您使用的语言)时,WebJob出现时将需要启动 清理并中断当前循环,最好退出该循环 正确,Azure将继续关闭该站点的过程.

Any WebJob that wants to listen on the shutdown notification will actually have to check for the presence of the file (using simple File.Exists function or using a FileSystemWatcher in whatever script language you use), when it shows up the WebJob will need to start cleaning up and break it's current loop where preferably it'll exit properly and Azure will continue the shutdown (of the site) process.

好吧,听起来好像没有什么好玩的.虽然阿米特(Amit)和其他人已经发布了一些代码来处理此问题(请参阅该帖子),但我发现它仍然比我想要的更加笨拙(我更喜欢丑陋的细节在代码中处理一次,然后立即依赖并忘记).我希望以下是更好的改进.我确实想要关闭设置的单行通知,而这就是我们现在所拥有的以下内容.我刚刚测试了此解决方案,关闭了工作,然后正确启动了.

Well, that doesn't sound like much fun having to handle. While Amit and others have posted some code to handle this (see that post), I found it still more unwieldy than I would like (I prefer ugly details to be taken care of in code once, and then promptly relied on and forgotten). I hope the following is a better improvement. I really wanted a single line notification of shutdown setup, and that's what we have now with the following. I just tested this solution, shut down my job and it fired correctly.

所有工作都放在一个单独的文件/类型中,我将其命名为WebJobShutdownNotifier.首先,用法:只需在Main方法中实例化此类型,然后传递具有关闭功能的void函数(或lamda)即可.而已!它将触发您的关机"方法,无需多说.我建议WebJobs团队将其或类似内容直接整合到JobHost中.只需提供一个活动即可订阅.

All the work is placed in a separate file / type, which I named WebJobShutdownNotifier. First, the usage: just instantiate this type in your Main method and pass a void function (or lamda) having the shutdown work. That's it! It will fire your Shutdown method, not much else to say about it. I suggest to the WebJobs team they incorporate this or something like it directly within the JobHost. Just provide an event to subscribe to.

示例用法:

    public static void Main() // your Main method...
    {
        // nice! a single line to handle the shutdown notification, firing your IsShuttingDown method
        var shutdownNotifier = new WebJobShutdownNotifier(IsShuttingDown);

        var host1 = new JobHost();
        host1.RunAndBlock();
    }

    public static void IsShuttingDown()
    {
        Console.WriteLine("Were shutin' down the webjob hatches baby! - {0}", DateTime.UtcNow);
        // do something else here if needed...
    }

//-WebJobShutdownNotifier.cs ---

// --- WebJobShutdownNotifier.cs ---

using System;
using System.IO;

namespace Microsoft.Azure.WebJobs.Helper
{
    /// <summary>
    /// Base info and code adapted and expanded from Amit Apple:
    /// http://blog.amitapple.com/post/2014/05/webjobs-graceful-shutdown/.
    /// To change the wait on shutdown time from the default of 5 seconds:
    /// "create a file called settings.job with the following content: { "stopping_wait_time": 60 }""
    /// (Nicholas Petersen)
    /// </summary>
    public class WebJobShutdownNotifier
    {
        public bool IsRunning { get; private set; }

        public string ShutdownFilePath { get; private set; }

        public bool FileEnvironmentVariableExisted { get; private set; }

        /// <summary>
        /// Set this as an action allowing you to be notified when it fires that 
        /// shutdown has been triggered (/detected).
        /// </summary>
        public Action IsShuttingDownNotifier { get; set; }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="isShuttingDownNotifier">
        /// Set this as an action allowing you to be notified when it fires that 
        /// shutdown has been triggered (/detected).
        /// </param>
        public WebJobShutdownNotifier(Action isShuttingDownNotifier = null, bool exceptionIfNoFileEnvironmentVariable = false)
        {
            IsRunning = true;
            IsShuttingDownNotifier = isShuttingDownNotifier;

            // Get the shutdown file path from the environment
            ShutdownFilePath = Environment.GetEnvironmentVariable("WEBJOBS_SHUTDOWN_FILE");

            FileEnvironmentVariableExisted = !string.IsNullOrEmpty(ShutdownFilePath);

            if (!FileEnvironmentVariableExisted) {
                if (exceptionIfNoFileEnvironmentVariable)
                    throw new Exception("WEBJOBS_SHUTDOWN_FILE Environment variable returned null or empty.");
            }
            else {
                // Setup a file system watcher on that file's directory to know when the file is created
                var fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(ShutdownFilePath));
                fileSystemWatcher.Created += OnChanged;
                fileSystemWatcher.Changed += OnChanged;
                fileSystemWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastWrite;
                fileSystemWatcher.IncludeSubdirectories = false;
                fileSystemWatcher.EnableRaisingEvents = true;
            }
        }

        private void OnChanged(object sender, FileSystemEventArgs e)
        {
            if (IsRunning) { // this was hitting more than once in the short shut down time, do not want to fire IsShuttingDownNotifier more than once...
                if (e.FullPath.IndexOf(Path.GetFileName(ShutdownFilePath), StringComparison.OrdinalIgnoreCase) >= 0) {
                    // Found the file mark, this WebJob has finished
                    IsRunning = false;
                    if (IsShuttingDownNotifier != null)
                        IsShuttingDownNotifier();
                }
            }
        }

    }
}

这篇关于正常关闭Azure WebJobs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆