【问题标题】:How to delay process using Azure functions?如何使用 Azure 函数延迟进程?
【发布时间】:2017-08-16 06:26:35
【问题描述】:

我需要延迟 DB2 中数据插入的执行。我需要等待 10 分钟才能收到following DB deployment reason

注册流程

  • 第 1 步:我在 DB1 的表中创建了一个条目。
  • 第 2 步:开始创建 DB2 的过程- 数据库创建 DB2
  • 第 3 步:10 分钟后需要进入已创建的 DB2。

如何使用 Azure 函数来实现?

【问题讨论】:

    标签: azure azure-functions azure-functions-runtime


    【解决方案1】:

    一种方法是将消息发送到服务总线队列,并将ScheduledEnqueueTimeUtc 属性设置为从现在起 10 分钟后。 (docs)

    然后有一个由该服务总线队列触发的 Azure 函数。 (docs)

    【讨论】:

      【解决方案2】:

      因为我需要等待 10 分钟,因为以下数据库部署原因:Not able to open Azure SQL Server DB immidiately after the creation

      由于全局配置选项host.jsonfunctionTimeout 的陈述如下:

      functionTimeout值表示所有函数的超时时间。

      • 在动态 SKU 中,有效范围为 1 秒到 10 分钟,默认值为 5 分钟。
      • 在付费 SKU 中没有限制,默认值为 null(表示没有超时)。

      据我了解,如果您的注册过程需要在CreateTenant下完成,我假设您可以在Step2之后检查您的数据库的创建状态,然后当数据库在线时,您可以进行Step3。我为这个场景写了一个示例,你可以参考它:

      run.csx

      #r "System.Configuration"
      #r "System.Data"
      
      using System.Net;
      
      using System.Configuration;
      using System.Data.SqlClient;
      using System.Threading.Tasks;
      
      public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
      {
          // Get request body
          dynamic data = await req.Content.ReadAsAsync<object>();
          string dataBase_Name = data?.dataBase_Name;
          string source_dataBase_Name = data?.source_dataBase_Name;
      
          log.Info("Begin create the database for the tenant...");
      
          //Create the database
          var str = ConfigurationManager.ConnectionStrings["sqldb_connection"].ConnectionString;
          using (SqlConnection conn = new SqlConnection(str))
          {
              conn.Open();
              var copyDbSql = $"CREATE DATABASE [{dataBase_Name}] as COPY OF [{source_dataBase_Name}] (SERVICE_OBJECTIVE='S0')";
              try
              {
                  using (SqlCommand cmd = new SqlCommand(copyDbSql, conn))
                  {   
                      //30s by default, https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout.aspx
                      //cmd.CommandTimeout=0; 
                      cmd.ExecuteNonQuery(); //30s timeout if the server is not responding, you could change it, but I would leave it for default.
                      log.Info("create database statement executed...");
                  }
              }
              catch (Exception e)
              {
                  //exception for timeout and so on
                  //you need to make sure the database creation has been accepted, you could execute the following sql statement:
                  //SELECT * FROM sys.dm_database_copies where partner_database=N'{your-database-name}'
                  log.Info(e.Message);
              }
          }
      
          log.Info("check the creation processing...");
          //If the database creation is accepted, then check the creation status of your database
          bool status = false;
          using (SqlConnection conn = new SqlConnection(str))
          {
              conn.Open();
              var text = "Select count(*) from master.sys.databases where name=N'" + dataBase_Name + "' and state_desc='ONLINE'";
              using (SqlCommand cmd = new SqlCommand(text, conn))
              {
                  do
                  {
                      var count = await cmd.ExecuteScalarAsync();
                      if (count != null && Convert.ToInt32(count) > 0)
                          status = true;
                      if (status)
                          log.Info($"Database [{dataBase_Name}] is online!!!");
                      else
                      {
                          log.Info($"Database [{dataBase_Name}] is creating...");
                          Task.Delay(TimeSpan.FromSeconds(30)).Wait(); //sleep for 30s
                      }
                  } while (!status);
              }
          }
      
          if (status)
          {
              //Database is online, do other operations
          }
          return req.CreateResponse(HttpStatusCode.OK, "");
      }
      

      结果:

      另外,正如 Mikhail 所建议的,您可以在执行数据库创建后发送队列消息,然后使用 QueueTrigger 获取消息并检查数据库的状态并在数据库联机后插入条目以解耦您的注册过程。

      这里有一些有用的教程,你可以参考一下:

      Use Azure Functions to connect to an Azure SQL Database

      sys.dm_database_copies (Azure SQL Database)

      【讨论】:

        【解决方案3】:

        我认为在 Azure Function V2 和 Durable Functions 扩展之后,现在有很多解决方案:

        1- 您可以使用 Durable Functions (link),这样您就可以编排整个工作流程,然后将您想要延迟的所有代码放在单独的函数中,然后使用正常的 Task.Delay 延迟它

        2- 您可以使用 Azure Logic Apps,您可以对其进行配置并安排它根据时间运行 (link)。

        3- 您还可以使用计划的服务总线队列 (link)。

        4- 您可以通过使用 SQL 作业在数据库端自行设置延迟来开箱即用,但这取决于您的业务和架构。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-31
          • 2020-03-19
          • 1970-01-01
          • 2015-05-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多