Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 控制azure WebJob函数调用_Sql Server_Multithreading_Azure_Azure Webjobs_Azure Webjobssdk - Fatal编程技术网

Sql server 控制azure WebJob函数调用

Sql server 控制azure WebJob函数调用,sql-server,multithreading,azure,azure-webjobs,azure-webjobssdk,Sql Server,Multithreading,Azure,Azure Webjobs,Azure Webjobssdk,我有一个Azure连续web作业,它有两种方法。第一个方法CleanupDb是[Singleton],每5分钟触发一次,第二个多线程方法ProcessXML使用队列触发。ProcessXml将数据从blob存储中存储的xml大容量复制到数据库,但当CleanupDb方法运行时,我希望: 在CleanupDb期间挂起ProcessXml的队列触发器 等待ProcessXml的任何当前实例完成 对数据库执行更新 数据库清理完成后,重新启用对ProcessXml的调用 我怎样才能做到这一点?我是否需要

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

  • 在CleanupDb期间挂起ProcessXml的队列触发器
  • 等待ProcessXml的任何当前实例完成
  • 对数据库执行更新
  • 数据库清理完成后,重新启用对ProcessXml的调用
  • 我怎样才能做到这一点?我是否需要使用信号量或互斥来进行线程间通信?是否可以禁用QueueTrigger?最后,我应该在大容量复制操作中使用TabLock吗?目标表有聚集索引,但我没有注意到问题

        [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]);
            }
    
    
        }
    

    一旦队列触发器运行,就无法临时禁用它。我还要提到,默认情况下TimerTrigger已经是单例的了。它在后台使用单例锁,以确保只有一个调度函数的实例在扩展实例上运行。因此,可能不需要额外的单例属性

    一种选择是在两个函数上使用singleton,使用相同的锁作用域(例如,
    [singleton(“xmlimport”)]
    )。这将确保函数不会同时运行——它们都需要相同的锁。例如,当运行
    CleanupDB
    时,任何
    ProcessXML
    调用都将等待锁定,反之亦然。这样做的一个潜在缺点是,您的队列函数现在也将被序列化——一次只处理一条队列消息,即使您的clean函数没有运行。如果您希望队列具有高吞吐量,那么您可能不希望这样。但是,如果导入操作不经常发生,这可能是您的一个选择

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


    另一种选择是确保数据库清理存储过程可以并发运行,这样就不必担心同步问题。不确定这是否是你的选择。例如,确保清理操作仅对旧数据进行操作,以便进行中的导入不会产生干扰,等等。

    因此,事实证明,您当前不能像上面所述那样在函数实例中实际使用单例。默认情况下,用于锁的blob路径始终包含完全限定的函数名。我已经在我们的公共回购协议中创建了一个应用程序来启用此场景。谢谢-看起来最好的选择可能是确保cleanupdb只在“旧”数据上运行。为了有效地做到这一点,我可能需要某种“滚动”分区方案——我一直在研究这个问题。可能是因为BulkCopy正在放置TabLock,所以清理数据库当前不工作-我将尝试删除它。查看github-我认为我是正确的,Singleton作用域的问题现在已通过azure web job sdk 1.1.1解决。是的,1.1.1中添加了对此的支持。你可以在维基上阅读更多。谢谢mathewc。当我对两个或多个计时器函数使用相同的单例锁时会发生什么?如果一个进程锁定另一个进程,那么锁定的进程会在失败时重试吗?例如,如果我有一个计时器每5分钟启动一次,如果5分钟的计时器进程发生溢出并“锁定”,那么每天的计时器是否会在不等待24小时的情况下重试?