web-dev-qa-db-fra.com

Comment mettre en attente les tâches en arrière-plan dans l'API Web ASP.NET

J'ai un site Web conçu pour traiter les rapports en file d'attente. Les étapes à suivre par l'application sont les suivantes:

  • Recevoir du contenu
  • Mappez le contenu sur un objet et placez-le dans la file d'attente
  • Interroger les éléments en attente dans la file d'attente
  • Traiter les éléments en file d'attente l'un après l'autre

Je pensais utiliser Entity Framework pour créer une base de données d'éléments en file d'attente, tels que:

public class EFBatchItem
{
    [Key]
    public string BatchId { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateCompleted { get; set; }
    public string BatchItem { get; set; }
    public BatchStatus Status { get; set; }
}

Ma question - Existe-t-il un moyen plus efficace, à l'aide de NServiceBus, BlockingCollection ou ConcurrentQeueue, que d'interroger en permanence la base de données et d'extraire les éléments en attente un par un? Je n'ai pas utilisé les files d'attente avant.

Une idée est de créer une file d'attente de tâches et de traiter toutes les tâches en attente sur un thread séparé. Quelque peu similaire à Le moyen le plus efficace de traiter une file d'attente avec des threads mais je veux m'assurer que mon itinéraire est le plus efficace.

EDIT: Une grande question que j'ai ici est la meilleure façon d'afficher les progrès à l'utilisateur. Une fois que l'utilisateur a soumis le contenu, il est redirigé vers une nouvelle page et peut afficher le statut à l'aide de l'identificateur de lot. MSMQ ou NServiceBus sont-ils nécessaires pour informer l'utilisateur? Cela ressemble-t-il à une variante du paradigme Demande/Reconnaître/Pousser?

15
appsecguy

IMHO, votre application API Web ASP.NET ne doit pas exécuter ces tâches en arrière-plan par elle-même. Il ne devrait être responsable que de recevoir la demande, de la coller dans la file d'attente (comme vous l'avez indiqué) et de renvoyer la réponse indiquant le succès ou l'échec du message reçu. Vous pouvez utiliser divers systèmes de messagerie tels que RabbitMQ pour cette approche.

En ce qui concerne la notification, vous avez quelques options. Vous pouvez avoir un noeud final sur lequel le client peut vérifier si le traitement est terminé ou non. Vous pouvez également fournir un point de terminaison d'API de diffusion auquel votre client peut s'abonner. De cette façon, le client n'a pas à interroger le serveur; le serveur peut notifier les clients connectés. L'API Web ASP.NET est un excellent moyen de le faire. Le blog suivant explique comment:

Vous pouvez également considérer SignalR pour ce type de notifications serveur à client.

La raison pour laquelle les tâches en arrière-plan sont difficiles pour l'application API Web ASP.NET est qu'il vous incombe de maintenir l'AppDomain en vie. C'est un problème surtout lorsque vous hébergez sous IIS. Les articles de blog suivants expliquent vraiment bien ce que je veux dire:

25
tugberk

Il s’agit d’un paquet NuGet appelé HangFire - https://github.com/HangfireIO/Hangfire . Les tâches persistent même au-delà du recyclage de l’apppool.

5
Todd

J'aime la solution de @ Todd. Juste pour être complet, mais il y a une autre option qui n'a pas encore été mentionnée:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    // Some long-running job
});

Remarque:

"Lorsque ASP.NET doit recycler, il avertit le travail d’arrière-plan (en définissant un CancellationToken) et attend ensuite 30 secondes pour que le travail soit terminé. Si le travail d’arrière-plan ne s’achève pas dans ce laps de temps, le travail disparaîtra mystérieusement. "

Et évitez d’utiliser des méthodes de service avec un DbContext injecté ici car cela ne fonctionnera pas.

Sources: MariusSchulz et StephenCleary

2
Anytoe

Si vous utilisez Asp.net Core, vous pouvez utiliser IHostService .

0
menxin