我打算使用连续的Azure WebJob来发送电子邮件和推送通知.我知道WebJobs会因各种原因不时启动和停止.这没关系,但我希望有机会在工作关闭前"清理".
这样我的WebJob就可以更新数据库记录的状态或删除每个批处理中已处理的队列项,这样下次作业运行时就不会发送重复的消息.
作为一个黑暗的镜头,我尝试将以下代码添加到我的C#控制台应用程序:
Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
{
e.Cancel = true;
program.keepRunning = false;
};
Run Code Online (Sandbox Code Playgroud)
然后我使用keepRunning bool来控制main while循环,并在while循环之外放置一个Console.Writeline("Exited Gracefully").但这似乎没有帮助.当我告诉作业停止时(使用我的Azure网站的Webjobs选项卡中的停止按钮),作业从列表中消失,并显示"无法停止作业:'JobName'." 在Azure门户中(位于页面底部).我没有看到WebJob日志中的"Exited Gracefully"文本.所以我把那个代码拿出来,因为它没有帮助.
所以,我正在寻找一个好方法,让我的WebJob被通知其秒数已经编号,并且需要按顺序获取其事务.
我相信Amit在最后一次回答之后很快就会发生变化,事实上根据他自己的博客帖子: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...
}
Run Code Online (Sandbox Code Playgroud)
// --- 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();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5580 次 |
| 最近记录: |