2017-10-13 5 views
2

J'essaie de trouver une solution à une action d'envoi d'e-mail qui peut prendre beaucoup de temps et de temps sur notre équilibreur de charge qui se trouve sur Rackspace. La seule question que je pouvais trouver qui se rapporte à cette question spécifique est la suivante:Arrêtez l'action qui retarde l'équilibreur de charge

keep load balancer from timing out during long operation

Si je comprends bien que je dois exécuter une autre action tandis que la principale action lente est terminé au sondage en permanence et de retour afin de garder choses en vie. Mon action email contient les éléments suivants:

var sendto = db.Users 
        .Where(b => b.Id == model.SentTo | 
        ((model.SelectedRoles.Any(s => b.Roles.Select(h => h.RoleId).Contains(s))) 
        && ((b.enrollment.Any(h => h.cohort.CourseID == model.CourseID) | model.CourseID == null)) 
        && (b.OrgID == model.OrgID | model.OrgID == null))).ToList(); 

        foreach (var address in sendto) 
        { 
         string Body = "message goes here"; 

         EmailConfig.SendMessageViaMailGun(filestoattach, address.Email, null, email.Subject, Body); 
        } 

Ainsi, une liste est créée puis boucle à travers les courriels envoyés à chaque personne sur la liste. La réponse de la méthode asynchrone dans la question ci-dessus semble faire l'affaire mais dans les commentaires je peux voir que c'est une mauvaise idée. Il est également obsolète en ce qui concerne la façon dont async fonctionne dans la dernière version de MVC.

Ma question est quelle est la meilleure façon de garder cette action de temporiser sur l'équilibreur de charge pendant qu'il se termine?

+2

Vous devez déplacer cette logique en dehors du serveur Web. Fondamentalement, votre serveur Web doit mettre en file d'attente une demande (par exemple, à RabbitMQ), puis un service distinct fonctionnant ailleurs devrait la supprimer et envoyer les courriels. – mjwills

Répondre

3

Cela n'a rien à voir avec async, c'est un problème d'infrastructure.

Il existe deux façons d'effectuer des opérations longues:

  1. La bonne façon: ont un serveur principal et un processus en cours d'exécution il y a + communiquer à ce processus de back-end via des files d'attente (ou interrogation de base de données), le client mises à jour en fonction de la progression (stockées dans certaines bases de données) et mise à jour de l'interface utilisateur sur le serveur Web. Vous devez également suivre la progression sur le backend pour continuer en cas d'arrêt inattendu.

  2. Le moyen le moins cher: Filtrer un thread différent (ou une tâche) sur le serveur web, et lui faire effectuer l'opération, et interroger à partir de javascript la progression de ce fil. Cela pourrait toutefois se fermer à tout moment (webserver recycle) et vous perdez l'opération (si vous êtes d'accord avec cela), alors vous devez reprendre l'opération et continuer. Un moyen grossier serait d'envelopper tout ce que vous avez avec Task.Run, et revenez tout de suite, puis interroger la progression de Javascript, mais comme je l'ai dit ci-dessus, il est sujet à des interruptions.

+0

Bonjour, merci pour votre réponse. Donc, si par exemple je mets les choses en place pour que la liste des emails soit mise à jour et que les emails soient envoyés et que l'action commence, j'ai utilisé signalR pour vérifier cela toutes les 5 secondes et renvoyer un message à la page mise à jour sur les progrès avant de cesser les opérations une fois qu'il pourrait voir qu'il n'y avait pas de messages laissés pour mettre fin à ce serait effectivement ce que vous parlez en 1? Cela permettrait également de garder l'équilibreur de charge de temporisation également? – Rob

+0

Oui, cela devrait fonctionner. – albattran