0
votes

Modèle d'envoi de messages aux sujets lorsque l'état de l'entité change

Nous utilisons un bus de service Azure pour informer les abonnés lorsqu'une entité de notre application est passée à un certain État. À l'heure actuelle, nous faisons cela juste après avoir appelé dbcontext.savechangeSasync ():

  1. dbcontext.savechangeSasync ()

  2. topicclient.sendasync (Somemessage)

    Le problème que j'ai, c'est ceci: dites que dbcontext.savechangeSasync () passe bien, mais pour une raison quelconque de l'appel à topicclient.Sendasync () jette une exception. Maintenant, les abonnés de ce sujet ne seront pas au courant de la modification de l'état de l'entité.

    J'ai essayé d'utiliser des transactionsCope, mais cela ne fonctionne pas car, comme je l'ai rassemblé, Azure n'utilise pas le DTC.

    (Je pourrais changer l'ordre des 2 étapes ci-dessus, mais si le message envoie une amende et que la sauvegarde échoue, le message contient des données FONGUS.)

    Quelqu'un a-t-il des suggestions sur la manière de gérer ce problème? Il semble que celui qui devrait être commun, mais je ne trouve rien en ligne. Si quelqu'un pouvait me diriger dans la bonne direction, je l'apprécierais.

    Merci d'avance.


0 commentaires

3 Réponses :


0
votes

Vous pouvez implémenter le modèle appelé File d'attente de message empoisonnée ou Quue de lettre morte . Il existe d'autres synonymes connus tels que Testez la file d'attente .

L'idée est d'essayer une opération et si elle ne réussit pas, mettez de la métainformation dans une file d'attente et de réessayer cette opération plus tard. Dans votre cas, après dbcontext.savechangeSasync () est appelé, vous pouvez mettre toutes les informations nécessaires dans une file d'attente durable et avoir un gestionnaire qui traitera cette file d'attente et en quelque sorte de processMessage () Vous pouvez gérer des appels de TopicClient.Sendasync (Somemessage) .
Par exemple, si l'appel au service de service ne réussit pas, vous pouvez retourner l'élément de la file d'attente dans la file d'attente pour le traitement ultérieur.

Bien sûr, vous pouvez dédier la file d'attente mentionnée uniquement pour les appels défaillants de TopicClient.Sendasync (SOMEMESSAGE) , qui peut réduire considérablement sa taille. L'ordre de fonctionnement est insignifiant, car vous pouvez mettre n'importe quelle métainformation, ce qui permet de faire appeler topicClient.sendasync (SOMEMESSAGE) Tout d'abord, puis essayez de mettre à jour la base de données.


0 commentaires

0
votes

Pas une réponse directe au problème à laquelle vous êtes confronté, mais je vais partager la manière dont nous avons résolu un problème similaire dans l'une de nos applications où nous avons dû écrire des données pour séparer les tableaux de stockage de table Azure. Parce que nous écrivions des données pour séparer les tableaux, nous ne pouvions pas utiliser la fonctionnalité de transaction par lots d'entité disponible dans le stockage de table Azure.

La façon dont nous avons résolu ce problème consiste à mettre en œuvre quelque chose de similaire à Modèle de consistance éventuelle .

Ce que nous faisons est au lieu d'effectuer des données d'enregistrement directement dans les tableaux (ce qui signifie que de multiples demandes de réseau pouvaient échouer), nous envoyons les données à enregistrer dans une file d'attente (la file d'attente de stockage). Si nous sommes en mesure de sauvegarder les données de la file d'attente, cela signifie que les données seront éventuellement disponibles.

Ensuite, nous avons écrit une fonction déclenchée de la file d'attente Azure. Dans cette fonction, nous économisons des données dans les tableaux où nous devrions économiser. Une fois que toutes les opérations réussissent, le message est automatiquement supprimé par la fonction Runtime. Si toute partie de l'opération échoue, le message sera envoyé à la file d'attente et sera à nouveau détresse.

Maintenant, une chose importante à comprendre est que ces méthodes de sauvegarde doivent être idempotentes. Disons que nous écrivons dans 3 tables et une opération d'écriture pour la 1ère table réussit, mais l'opération d'écriture pour la 2e table échoue. La prochaine fois que la fonction est invoquée, elle tentera d'écrire à la 1ère table et le code doit pouvoir gérer ce gracieusement.


1 commentaires

Merci beaucoup. Je vais regarder dans ça.



1
votes

Comme vous avez décrit, l'ordre des opérations n'aura pas d'importance car il n'ya aucune transaction qui se chevauche entre les deux services, la base de données et le service de messagerie. Si le magasin de données que vous utilisez des opérations de support (par exemple, Azure SQL Server), vous pouvez vous éloigner sans utiliser de commettre deux phases et regarder dans la mise en œuvre du modèle de boîte d'envoi .

NSERVICEBUS fournit le modèle en tant que Fonction . Vous pouvez télécharger la boîte d'envoi échantillon qui montre comment l'utiliser avec RabbitMQ. Le transport peut être remplacé par Transport de bus de service Azure pour répondre à votre exigence.

Divulgation: je contribue à NSERVICEBUS.


3 commentaires

Merci beaucoup. Je vais vérifier cela.


J'ai fini par aller avec le modèle de boîte d'envoi transactionnel, comme vous l'avez suggéré, avec une implémentation ihostedService pour surveiller la table des boîtes d'envoi. Merci pour la suggestion et désolé, il m'a fallu si longtemps pour que je réponde.


Heureux d'entendre c'était ce que vous cherchez. Et toujours génial d'entendre une confirmation, merci. 🙂