简体   繁体   English

Azure持久编排功能触发两次

[英]Azure Durable orchestration function triggering twice

I am trying to implement an Azure Durable Function workflow. 我正在尝试实现Azure耐用功能工作流。

Every 6 minutes I have an Azure TimerTrigger function calls an Azure Orchestration Function (OrchestrationTrigger), that in turn starts a number of activity functions (ActivityTrigger). 我每隔6分钟就有一个Azure TimerTrigger函数调用一个Azure编排函数(OrchestrationTrigger),该函数又启动了许多活动函数(ActivityTrigger)。

Sometimes, however, the Orchestration function gets called twice in the span of a few seconds! 但是,有时候,编排功能会在几秒钟的时间内被调用两次! This is a big problem as my activity functions are not idempotent! 这是一个大问题,因为我的活动功能不是幂等的!

Below is how my code gets called. 以下是我的代码的调用方式。

TimerTriggered Function: TimerTriggered函数:

[FunctionName("StartupFunc")]
public static async Task Run([TimerTrigger("0 */6 * * * *", RunOnStartup = true, UseMonitor = false)]TimerInfo myStartTimer, [OrchestrationClient] DurableOrchestrationClient orchestrationClient, TraceWriter log)
{
    List<OrchestrationModel> ExportModels = await getData();

    string id = await orchestrationClient.StartNewAsync("OrchestratorFunc", ExportModels);
}

Orchestration Function: 编排功能:

[FunctionName("OrchestratorFunc")]
public static async Task<string> TransformOrchestration([OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log)
{
    var dataList = context.GetInput<List<OrchestrationModel>>();
    var tasks = new List<Task>();

    foreach (var data in dataList)
    {
        tasks.Add(context.CallActivityAsync<string>("TransformToSql", new TransformModel(data));
    }
    await Task.WhenAll(tasks);
}

Activity function: 活动功能:

[FunctionName("TransformToSql")]
[public static async Task<string> RunTransformation([ActivityTrigger] DurableActivityContext context, TraceWriter log)
{
    TransformModel = context.GetInput<TransformModel>();

    //Do some work with TransformModel
}

This behaviour is perfectly fine - this is how Durable Functions works by design. 这种行为非常好-耐用功能是设计使然的。

You have the following orchestration: 您具有以下业务流程:

[FunctionName("OrchestratorFunc")]
public static async Task<string> TransformOrchestration([OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log)
{
    var dataList = context.GetInput<List<OrchestrationModel>>();
    var tasks = new List<Task>();

    foreach (var data in dataList)
    {
        tasks.Add(context.CallActivityAsync<string>("TransformToSql", new TransformModel(data));
    }
    await Task.WhenAll(tasks);
}

When an activity is called, the flow returns to a concept called Dispatcher - it is an internal being of Durable Functions, responsible for maintaining the flow of your orchestration. 调用活动时,流程返回到称为Dispatcher的概念-它是具有持久功能的内部实体,负责维护业务流程。 As it awaits until a task is finished, an orchestration is deallocated temporarily. 等待任务完成之前,业务流程被临时释放。 Once a task is completed, the whole orchestration is replayed until the next await happens. 一旦任务完成,整个业务流程将重播,直到下一次await

The important thing there is, though an orchestration is replayed, an activity is not called once more - its result is fetched from the storage and used. 重要的是,尽管重播了业务流程,但活动不再被调用-它的结果是从存储中获取并使用的。 The make things more explicit, please consider the following example: 使事情更明确的,请考虑以下示例:

[FunctionName("OrchestratorFunc")]
public static async Task<string> TransformOrchestration([OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log)
{
    var dataList = context.GetInput<List<OrchestrationModel>>();
    var tasks = new List<Task>();

    foreach (var data in dataList)
    {
        await context.CallActivityAsync<string>("TransformToSql1", new TransformModel(data);
        await context.CallActivityAsync<string>("TransformToSql2", new TransformModel(data);
    }
}

When TransformToSql1 is awaited, the orchestration is deallocated and the whole flow waits until this activity is finished. 等待TransformToSql1 ,将取消分配业务流程,整个流程将一直等到此活动完成。 Then the orchestration is replayed - it once more awaits TransformToSql1 but since the result of it is saved, it just goes back to the orchestration and awaits TransformToSql2 - then the process is repeated. 然后,重新编排业务流程-它再次等待TransformToSql1但是由于保存了结果,因此它又回到业务流程并等待TransformToSql2然后重复该过程。

The orchestration function will run more frequently as it is replayed by the Durable Function framework. 随着持久功能框架的重播,业务流程功能将更频繁地运行。 Do you see that your activity functions are also triggered again? 您是否看到活动功能也被再次触发? If so then this is indeed a strange behavior. 如果是这样,那确实是一种奇怪的行为。

Durable Functions uses storage queues and tables to control the flow and capture state of the orchestration. 持久功能使用存储队列和表来控制流程的流程和捕获状态。

Each time the orchestration function is triggered (by receiving a message from the control queue) it will replay the orchestration. 每次触发业务流程功能时(通过从控制队列接收消息),都会重播业务流程。 You can check this in code by using the IsReplaying property on the DurableOrchestrationContext . 您可以使用IsReplaying上的DurableOrchestrationContext属性在代码中进行检查。

if (!context.IsReplaying)
{
   // this code will only run during the first execution of the workflow
}

Don't use the IsReplaying to determine to run the activities, but use it for logging/debugging purposes. 不要使用IsReplaying确定运行活动,而IsReplaying其用于记录/调试目的。

When an activity function is reached a message is put on the work-item queue. 当达到活动功能时,将一条消息放入工作项队列。 The Durable Functions framework will then look into the history table to determine if this activity function has already been run before (with the given parameters). 然后,“耐用功能”框架将查看历史记录表,以确定此活动功能是否之前已经运行过(具有给定的参数)。 If it is, then it won't run the activity function again and it will continue with the rest of the orchestration function. 如果是这样,则它将不会再次运行活动功能,它将继续执行业务流程的其余部分。

The checkpointing and replay functionality of Durable Functions only works when the orchestration code is deterministic. 持久功能的检查点和重播功能仅在业务流程代码具有确定性时才起作用。 So never use decisions based on DateTime or random numbers. 因此,切勿使用基于DateTime或随机数的决策。

More info: https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-checkpointing-and-replay 更多信息: https : //docs.microsoft.com/zh-cn/azure/azure-functions/durable-functions-checkpointing-and-replay

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM