控制 azure WebJob 函数调用
Controlling azure WebJob function calls
我有一个 Azure 连续 Web 作业,它有几种方法。第一个方法 CleanupDb 是一个 [Singleton],每 5 分钟触发一次,第二个多线程方法 ProcessXML 使用队列触发。 ProcessXml 将数据从存储在 blob 存储中的 xml 批量复制到数据库,但是当 CleanupDb 方法运行时,我想:
- 在 CleanupDb
期间暂停 ProcessXml 的队列触发器
- 等待 ProcessXml 的任何当前实例完成
- 对数据库执行更新
- 数据库清理完成后,重新启用对 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 提供的。
另一种选择是确保您的数据库清理存储过程可以 运行 同时进行,这样您就不必担心同步问题。不确定这是否适合您。例如,确保清理操作只对旧数据进行操作,因此正在进行的导入不会干扰等。
我有一个 Azure 连续 Web 作业,它有几种方法。第一个方法 CleanupDb 是一个 [Singleton],每 5 分钟触发一次,第二个多线程方法 ProcessXML 使用队列触发。 ProcessXml 将数据从存储在 blob 存储中的 xml 批量复制到数据库,但是当 CleanupDb 方法运行时,我想:
- 在 CleanupDb 期间暂停 ProcessXml 的队列触发器
- 等待 ProcessXml 的任何当前实例完成
- 对数据库执行更新
- 数据库清理完成后,重新启用对 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 提供的。
另一种选择是确保您的数据库清理存储过程可以 运行 同时进行,这样您就不必担心同步问题。不确定这是否适合您。例如,确保清理操作只对旧数据进行操作,因此正在进行的导入不会干扰等。