控制 azure WebJob 函数调用

Controlling azure WebJob function calls

我有一个 Azure 连续 Web 作业,它有几种方法。第一个方法 CleanupDb 是一个 [Singleton],每 5 分钟触发一次,第二个多线程方法 ProcessXML 使用队列触发。 ProcessXml 将数据从存储在 blob 存储中的 xml 批量复制到数据库,但是当 CleanupDb 方法运行时,我想:

  1. 在 CleanupDb
  2. 期间暂停 ProcessXml 的队列触发器
  3. 等待 ProcessXml 的任何当前实例完成
  4. 对数据库执行更新
  5. 数据库清理完成后,重新启用对 ProcessXml 的调用。

我怎样才能做到这一点?我是否需要使用信号量或互斥量进行线程间通信?是否可以禁用 QueueTrigger?最后,我是否应该在批量复制操作中使用 TabLock - 目标 table 有一个聚集索引,但我没有注意到问题?

    [Singleton]
    public async static Task CleanupDb([TimerTrigger("0 0/5 * * * *", RunOnStartup = false)]TimerInfo info, TextWriter log)
    {

        // disable any calls to ProcessXML based on import-request queue
        // Wait for any current calls to ProcessXML to complete

        using (XmlNetworkModel ctxt = new XmlNetworkModel())
        {
            ctxt.Database.CommandTimeout = 0;
            await ctxt.Database.ExecuteSqlCommandAsync("exec stpCleanupDb");

        }

        // re-enable calls to ProcessXML


    }


    // This function will get triggered/executed when a new message is written 
    // on an Azure Queue called queue.
    public async static Task ProcessXML(
        [QueueTrigger("import-request")] BlobInformation blobInfo,
        [Blob("import/{BlobName}", FileAccess.Read)] Stream blobInStream,
        [Blob("import/{BlobName}")] CloudBlockBlob blobIn, TextWriter log)
    {
        using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["model"].ConnectionString, 
                        SqlBulkCopyOptions.TableLock)) // should TableLock be used with parallel threads here?
        {

            await sqlBulkCopy.WriteToServerAsync([mydatafromblobInStream]);
        }


    }

一旦 运行ning 就无法暂时禁用队列触发器。我还会提到 TimerTrigger 默认情况下已经是 Singleton。它在幕后需要一个单例锁,以确保您的计划函数只有一个实例 运行ning 在横向扩展的实例中。因此,您可能不需要额外的 Singleton 属性。

一个选项是在两个函数上使用单例,使用相同的锁范围(例如[Singleton("xmlimport")])。这将确保函数不会 运行 同时发生——它们都需要相同的锁。例如,虽然 CleanupDB 是 运行ning,但任何 ProcessXML 调用都将等待锁定,而 vice-versa。一个潜在的缺点是 你的队列函数现在也将被序列化 - 一次只会处理一个队列消息,即使你的清理函数不是 运行宁。如果您希望队列有高吞吐量,您可能不希望那样。但如果导入操作不经常发生,它可能是您的一个选择。

如果您已将 WebJob 扩展到多个实例,则使用进程内同步将不起作用,您将再次需要某种分布式锁定,如 Singleton 提供的。

另一种选择是确保您的数据库清理存储过程可以 运行 同时进行,这样您就不必担心同步问题。不确定这是否适合您。例如,确保清理操作只对旧数据进行操作,因此正在进行的导入不会干扰等。