【问题标题】:Troubleshooting automatic restart of Azure Web JobsAzure Web 作业的自动重新启动故障排除
【发布时间】:2018-02-09 01:15:19
【问题描述】:

我有一个 Azure 网站,用户可以在该网站上上传大量 XML 文件。这些文件都需要处理并填写到数据库中。

对于这个处理,我使用了一个 continue webjob。

出于非相关原因,所有上传的文件都需要按用户处理。 所以我有一个包含所有文件和用户 ID 的表。我有一张正在运行的工作表。我有多个 webjobs 执行相同的过程。如果需要处理任何文件,每个 webjob 都会在 files 表中查找。在启动之前,它会检查正在运行的作业表,如果另一个作业尚未处理用户的文件。

这工作正常,可以运行几个月没有任何问题。 但有时连续的网络作业正在重新启动。大部分时间是在晚上(我的时间),这让我错过了宝贵的处理时间。 我是唯一访问 Azure 的人。在重新启动之前,我没有部署任何新的东西。该作业在重新启动时大部分时间都在处理。所以内存问题可能是一个问题。但我正在运行 S3,最大 cpu 和内存不超过 40%。 日志记录也不是很有帮助:

[01/25/2018 05:03:20 > 5657e1: INFO] Starting job: 28158.
[01/25/2018 09:49:24 > 5657e1: SYS INFO] WebJob is still running
[01/25/2018 20:23:06 > 5657e1: SYS INFO] Status changed to Starting
[01/25/2018 20:23:06 > 5657e1: SYS INFO] WebJob singleton setting is False

由于网络作业没有很好地完成,正在运行的作业表没有更新。重新启动时,作业仍然认为用户的文件由另一个 Web 作业处理,从而使所有作业相互等待并且没有任何事情发生。

如何查看作业重新启动的原因?当我知道我可能会修复它的原因时。 非常感谢任何帮助。

更新 我更改了入口点,并在我的 main 方法的顶部添加了以下几行:

    // Get the shutdown file path from the environment
    _shutdownFile = Environment.GetEnvironmentVariable("WEBJOBS_SHUTDOWN_FILE");
    _log.Info("Watching " + _shutdownFile);
    // Setup a file system watcher on that file's directory to know when the file is created:
    var filename = Path.GetFileName(_shutdownFile);
    if (filename != null)
    {
        var fileSystemWatcher = new FileSystemWatcher(filename);
        fileSystemWatcher.Created += OnAzureRestart;
        fileSystemWatcher.Changed += OnAzureRestart;
        fileSystemWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastWrite;
        fileSystemWatcher.IncludeSubdirectories = false;
        fileSystemWatcher.EnableRaisingEvents = true;
        _log.Info("FileSystemWatcher is set-up");
    }

但在将其发布到 Azure 后,webjob 将无法启动,而是抛出错误:

[02/08/2018 15:23:56 > a93630: ERR ] Unhandled Exception: System.ArgumentException: The directory name gugfn3vx.0gk is invalid.
[02/08/2018 15:23:56 > a93630: ERR ]    at System.IO.FileSystemWatcher..ctor(String path, String filter)
[02/08/2018 15:23:56 > a93630: ERR ]    at System.IO.FileSystemWatcher..ctor(String path)
[02/08/2018 15:23:56 > a93630: ERR ]    at TaskRunner.Program.Main(String[] args)

我认为问题出在Path.GetFileName(_shutdownFile) 这一行,因为当网络作业仍在运行时该文件不存在。 还有什么建议吗?

更新 2 不知何故,我做了一个错误的代码更改。这是工作代码:

    // Get the shutdown file path from the environment
    _shutdownFile = Environment.GetEnvironmentVariable("WEBJOBS_SHUTDOWN_FILE");
    _log.Info("Watching " + _shutdownFile);
    // Setup a file system watcher on that file's directory to know when the file is created:
    var folder = Path.GetDirectoryName(_shutdownFile);
    if (folder != null)
    {
        var fileSystemWatcher = new FileSystemWatcher(folder);
        fileSystemWatcher.Created += OnAzureRestart;
        fileSystemWatcher.Changed += OnAzureRestart;
        fileSystemWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastWrite;
        fileSystemWatcher.IncludeSubdirectories = false;
        fileSystemWatcher.EnableRaisingEvents = true;
        _log.Info("FileSystemWatcher is set-up");
    }

更改在var folder = Path.GetDirectoryName(_shutdownFile);行中

【问题讨论】:

  • 这种情况多久发生一次?请注意,随着平台的升级,PaaS 环境中会出现一些重启。此外,您首先说您有一个 WebJob,然后说您有多个。你能澄清一下吗?
  • 我有两个相同作业的实例正在运行,因此可以处理两个用户的文件。我们现在已经运行了这个系统几个月,差不多一年了,我已经看过 6 次了。我并不总是看到重新启动发生的时间。我只在文件没有得到处理时才注意到它。然后我查看日志,发现它又重新启动了。
  • 你是在使用 WebJobs SDK,还是只是用你自己的逻辑来实现你的 WebJob?
  • 我没有使用 WebJobs SDK
  • 您是否使用here 描述的优雅关机模式?请注意,您应该每月至少看到一次重启,并且可能更多是由于平台升级。所以6次听起来不对。尽管您在此处看到的可能不是干净的重新启动,而是某种导致您在没有警告的情况下崩溃的崩溃。

标签: azure azure-webjobs


【解决方案1】:

我们在 cmets 中调查时概述了几个关键发现:

  • 为了获得最佳关闭行为,您的 WebJob 需要实现 graceful shutdown pattern,它主要包括侦听名为 %WEBJOBS_SHUTDOWN_FILE% 的文件的出现(注意:使用 WebJobs SDK 时不需要这样做,因为它会自动执行此操作)。
  • 随着平台的升级,PaaS 环境中会出现一些重新启动。一切都是为了不中断地处理它。

【讨论】:

  • 昨晚我又跑了一个大作业,大概需要4个小时。 3 小时后,Azure 决定再次重新启动。我可以看到我的检测工作正常,但我的 private static void OnAzureRestart(object sender, FileSystemEventArgs e) 正在另一个线程上运行。所以它无法访问我的类变量,因此无法重置我的进程。它需要我的private static RunningJob _currentJob;OnAzureRestart _currentJobNULL。请再指教。
  • 您指的是我无权访问的代码,因此有点难以评论。您可以做的是在看到更改时设置一些静态标志,然后让另一个线程检查该标志(例如在其主循环中)。但这实际上取决于您的代码的性质。
  • 再次感谢大卫的宝贵意见。我现在将我的变量传递给我的事件监听器,现在我不再有线程问题:fileSystemWatcher.Created += (sender, e) => OnAzureRestart(sender, e, _currentJob);private static void OnAzureRestart(object sender, FileSystemEventArgs e, RunningJob currentJob)