我相信在阿米特最后一次回答之后事情很快就发生了变化,根据他自己的博客文章实际上在这里:WebJobs Graceful Shutdown
还可以在 6:00+ 标记之后查看此视频,以对此进行一些讨论。
来自 Amit 的博客:
Azure 通知将要停止的进程的方式是在路径中放置(创建)一个文件,该路径作为名为 WEBJOBS_SHUTDOWN_FILE 的环境变量传递。
任何想要监听关闭通知的 WebJob 实际上都必须检查文件是否存在(使用简单的 File.Exists 函数或使用您使用的任何脚本语言的 FileSystemWatcher),当它显示时,WebJob 将需要启动清理并打破它的当前循环,最好它会正确退出,Azure 将继续关闭(站点)过程。
好吧,这听起来并不好玩。虽然 Amit 和其他人已经发布了一些代码来处理这个问题(见那篇文章),但我发现它仍然比我想要的更笨拙(我更喜欢在代码中处理丑陋的细节,然后迅速依赖并忘记)。我希望以下是更好的改进。我真的想要一个关机设置的单行通知,这就是我们现在拥有的以下内容。我刚刚测试了这个解决方案,关闭了我的工作并且它正确触发了。
所有的工作都放在一个单独的文件/类型中,我将其命名为 WebJobShutdownNotifier。首先,用法:只需在您的 Main 方法中实例化此类型并传递一个具有关闭工作的 void 函数(或 lamda)。而已!它会触发你的 Shutdown 方法,没什么好说的。我建议 WebJobs 团队将这个或类似的东西直接合并到 JobHost 中。只需提供要订阅的事件。
示例用法:
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 ---
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();
}
}
}
}
}