[英]Azure Durable orchestration function triggering twice
我正在嘗試實現Azure耐用功能工作流。
我每隔6分鍾就有一個Azure TimerTrigger函數調用一個Azure編排函數(OrchestrationTrigger),該函數又啟動了許多活動函數(ActivityTrigger)。
但是,有時候,編排功能會在幾秒鍾的時間內被調用兩次! 這是一個大問題,因為我的活動功能不是冪等的!
以下是我的代碼的調用方式。
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);
}
編排功能:
[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);
}
活動功能:
[FunctionName("TransformToSql")]
[public static async Task<string> RunTransformation([ActivityTrigger] DurableActivityContext context, TraceWriter log)
{
TransformModel = context.GetInput<TransformModel>();
//Do some work with TransformModel
}
這種行為非常好-耐用功能是設計使然的。
您具有以下業務流程:
[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);
}
調用活動時,流程返回到稱為Dispatcher的概念-它是具有持久功能的內部實體,負責維護業務流程。 等待任務完成之前,業務流程被臨時釋放。 一旦任務完成,整個業務流程將重播,直到下一次await
。
重要的是,盡管重播了業務流程,但活動不再被調用-它的結果是從存儲中獲取並使用的。 使事情更明確的,請考慮以下示例:
[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);
}
}
等待TransformToSql1
,將取消分配業務流程,整個流程將一直等到此活動完成。 然后,重新編排業務流程-它再次等待TransformToSql1
但是由於保存了結果,因此它又回到業務流程並等待TransformToSql2
然后重復該過程。
隨着持久功能框架的重播,業務流程功能將更頻繁地運行。 您是否看到活動功能也被再次觸發? 如果是這樣,那確實是一種奇怪的行為。
持久功能使用存儲隊列和表來控制流程的流程和捕獲狀態。
每次觸發業務流程功能時(通過從控制隊列接收消息),都會重播業務流程。 您可以使用IsReplaying
上的DurableOrchestrationContext
屬性在代碼中進行檢查。
if (!context.IsReplaying)
{
// this code will only run during the first execution of the workflow
}
不要使用IsReplaying
確定運行活動,而IsReplaying
其用於記錄/調試目的。
當達到活動功能時,將一條消息放入工作項隊列。 然后,“耐用功能”框架將查看歷史記錄表,以確定此活動功能是否之前已經運行過(具有給定的參數)。 如果是這樣,則它將不會再次運行活動功能,它將繼續執行業務流程的其余部分。
持久功能的檢查點和重播功能僅在業務流程代碼具有確定性時才起作用。 因此,切勿使用基於DateTime或隨機數的決策。
更多信息: https : //docs.microsoft.com/zh-cn/azure/azure-functions/durable-functions-checkpointing-and-replay
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.