如何使用 Azure 函数延迟进程?

How to delay process using Azure functions?

我需要延迟在DB2 中执行数据插入。 following DB deployment reason

我需要等待 10 分钟

注册流程

如何使用 Azure 函数实现?

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

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

Because I need to wait for 10 min for the following DB deployment reason : Not able to open Azure SQL Server DB immidiately after the creation

如全局配置选项 host.json 所述,关于 functionTimeout 如下:

functionTimeout Value indicating the timeout duration for all functions.

  • In Dynamic SKUs, the valid range is from 1 second to 10 minutes and the default value is 5 minutes.
  • In Paid SKUs there is no limit and the default value is null (indicating no timeout).

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

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)

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

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

2- 您可以使用 Azure 逻辑应用程序,您可以对其进行配置并根据时间 (link) 将其安排到 运行。

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

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