如何使用 Azure 函数延迟进程?
How to delay process using Azure functions?
我需要延迟在DB2 中执行数据插入。 following DB deployment reason
我需要等待 10 分钟
注册流程
- 第 1 步:我在 DB1 的 table 中创建了一个条目。
- 第 2 步:启动创建 DB2 的过程- 数据库创建 DB2
- 第 3 步:10 分钟后需要在创建的 DB2 中进行输入。
如何使用 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 获取消息并检查数据库的状态,并在数据库在线后插入条目以解耦您的注册过程。
这里有一些有用的教程,你可以参考一下:
我认为在 Azure Function V2 和 Durable Functions 扩展之后现在有很多解决方案:
1- 您可以使用 Durable Functions (link),这样您就可以编排整个工作流程,然后将您想要延迟的所有代码放在单独的函数中,然后使用正常的 Task.Delay
2- 您可以使用 Azure 逻辑应用程序,您可以对其进行配置并根据时间 (link) 将其安排到 运行。
3- 您还可以使用计划服务总线队列 (link)。
4- 您可以开箱即用,使用 SQL 作业在数据库端自行延迟,但这取决于您的业务和架构。
我需要延迟在DB2 中执行数据插入。 following DB deployment reason
我需要等待 10 分钟注册流程
- 第 1 步:我在 DB1 的 table 中创建了一个条目。
- 第 2 步:启动创建 DB2 的过程- 数据库创建 DB2
- 第 3 步:10 分钟后需要在创建的 DB2 中进行输入。
如何使用 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 获取消息并检查数据库的状态,并在数据库在线后插入条目以解耦您的注册过程。
这里有一些有用的教程,你可以参考一下:
我认为在 Azure Function V2 和 Durable Functions 扩展之后现在有很多解决方案:
1- 您可以使用 Durable Functions (link),这样您就可以编排整个工作流程,然后将您想要延迟的所有代码放在单独的函数中,然后使用正常的 Task.Delay
2- 您可以使用 Azure 逻辑应用程序,您可以对其进行配置并根据时间 (link) 将其安排到 运行。
3- 您还可以使用计划服务总线队列 (link)。
4- 您可以开箱即用,使用 SQL 作业在数据库端自行延迟,但这取决于您的业务和架构。