En bref, notre tâche consiste à traiter un grand nombre de messages d'entrée. Pour résoudre ce problème, nous avons décidé d'utiliser Azure Queue Storage et Azure Functions. Nous avons une structure Azure Functions similaire au code suivant:
Fonction déclenchée en file d'attente:
[FunctionName("MessageControllerExecutor")]
public static async void Run(
[QueueTrigger(QUEUE_NAME, Connection = QUEUE_CONNECTION_NAME)]string queueMessage,
[OrchestrationClient] DurableOrchestrationClient client,
TraceWriter log)
{
await client.StartNewAsync("MessageController", queueMessage);
}
Fonction durable:
[FunctionName("MessageController")]
public static async void Run(
[OrchestrationTrigger] DurableOrchestrationContext context,
TraceWriter log)
{
if (!context.IsReplaying) log.Warning("MessageController started");
var function1ResultTask = context.CallActivityAsync<ResultMessage>("Function_1", new InputMessage());
var function2ResultTask = context.CallActivityAsync<ResultMessage>("Function_2", new InputMessage());
await Task.WhenAll(function1ResultTask, function2ResultTask);
// process Function_1 and Function_2 results
// ...
}
Exemple de fonction d'activité simple:
[FunctionName("Function_1")]
public static ResultMessage Run(
[ActivityTrigger] DurableActivityContext activityContext,
TraceWriter log)
{
var msg = activityContext.GetInput<InputMessage>();
int time = new Random().Next(1, 3);
Thread.Sleep(time * 1000);
return new ResultMessage()
{
Payload = $"Function_1 slept for {time} sec"
};
}
MessageControllerExecutor est déclenché lorsqu'un nouvel élément est reçu dans une file d'attente. MessageController est une fonction durable qui utilise peu de fonctions d'activité simples pour traiter chaque message.
Lorsque nous transmettons des messages à la file d'attente, les fonctions MessageControllerExecutor démarrent immédiatement et de manière asynchrone, déclenchent MessageController et transmettent le message afin qu'il fonctionne comme prévu. Mais nous sommes confrontés au problème que toutes les fonctions de MessageController ne sont pas exécutées. Par exemple, nous avons mis 100 messages dans la file d'attente, mais seulement 10 à 20% des messages ont été traités par MessageController. Certains messages n'ont pas été traités ou ont été traités avec un long délai. Il semble que les fonctions durables n'aient pas démarré, bien qu'aucune exception n'ait été lancée.
Nous avons donc quelques questions:
Dans la question ci-dessus, vous avez éliminé du code de votre déclencheur d’orchestration dans un souci de concision que je comprends, mais que faites-vous exactement après la await Task.WhenAll(...)
? Si cela inclut tout type de traitement important, vous devriez vraiment le confier à une troisième fonction d'action (par exemple, Function_3
) à faire, puis renvoyer simplement les résultats de la fonction d'orchestration.
Mise à jour: Je viens de remarquer que vos fonctions sont définies par async void
. Si je devais deviner, cela poserait effectivement un problème pour l'exécution. Pouvez-vous essayer de le changer en async Task
et voir si votre problème disparaît? En règle générale définir des méthodes comme async void
est mal vu dans .NET .
Une extension pour la réponse de Drew. Vous ne devez pas utiliser Thread.Sleep (), car la documentation states utilise à la place CreateTimer Api.