当前位置:网站首页>. Net Core with microservices - Rapid Implementation of Distributed Transaction Based on reliable message Using agiledt

. Net Core with microservices - Rapid Implementation of Distributed Transaction Based on reliable message Using agiledt

2021-10-14 05:37:16 Agile. Zhou

Il y a eu plusieurs discussions sur les transactions distribuées(Cohérence finale des messages fiables Transactions distribuées - TCC Transactions distribuées - 2PC、3PC),Mais il n'y a pas eu de combat réel.Alors, dans cet article, nous allons vous montrer comment .NET Réaliser une transaction distribuée basée sur un message fiable dans un environnement.Les processus de transaction distribués basés sur des messages fiables sont encore assez clairs,Mais il est encore plus difficile d'implémenter un par un avec le Code.L'analyse montre que le point clé de cette transaction est d'être en avance sur la vraie logique d'entreprise、Insérer le processus correspondant après.Il est clair que ce processus peut passer par AOP Technologie pour simplifier le fonctionnement.Et voilà. AgileDT .AgileDT Utiliser Natasha Générer dynamiquement la classe proxy au démarrage,Pour compléter les opérations avec la section message pour vous,Les utilisateurs n'ont qu'à se soucier de la logique opérationnelle de base.
https://github.com/kklldog/AgileDT Open source n'est pas facile,Tout le monde!

Rétrospective

Article précédent(Cohérence finale des messages fiables )Nous Détaillons les transactions distribuées basées sur des messages fiables.Pour une meilleure compréhension AgileDT Code,Il est encore nécessaire d'examiner brièvement.


Le processus global du plan peut être divisé en étapes comme suit::

  1. L'initiateur envoie un message au service de messagerie fiable avant le début d'une véritable entreprise“À confirmer”Message de
  2. Le Service de messagerie fiable maintient le message dans la base de données après avoir reçu le message à confirmer
  3. Si l'opération ci - dessus est réussie, l'initiateur commence une véritable entreprise,Abandonner l'exécution de l'entreprise en cas d'échec
  4. Envoyer si l'opération est réussie“Confirmation”Message au service de messagerie fiable,Envoyer si l'exécution échoue“Annulation”Service de messagerie fiable.
  5. Si le Service de messagerie fiable reçoit“Confirmation”Le message met à jour l'état de l'enregistrement du message dans la base de données à“À envoyer”,Si le message reçu est“Annulation”L'état du message de mise à jour est“Annulé”
  6. Si la base de données mise à jour à l'étape précédente est“À envoyer”,Ça va commencer.MQEnvoyer un message,Et changer l'état des enregistrements de messages dans la base de données à“Envoyé”
  7. Avancez.MQAprès la livraison réussie du message,MQEnvoie un message à la partie passive.
  8. La partie passive commence à traiter les affaires après avoir reçu le message
  9. Si l'entreprise est traitée avec succès,Alors la paire passiveMQEn coursACKRéponse,Ce message sera envoyé à partir deMQRetrait interne
  10. Si l'entreprise est traitée avec succès,Envoyer“Terminé”Message au service de messagerie fiable
  11. Reçu par le Service de messagerie fiable“Terminé”Mise à jour de l'enregistrement des messages de la base de données après le message non“Terminé”

Arrête tes conneries.,Voyons comment utiliser AgileDT Pour réaliser rapidement une transaction distribuée basée sur un message fiable.
Ci - dessous, nous montrons également le scénario classique de commande pour compléter les points donnés aux membres..

Utiliser AgileDT

Composante dépendante

  • mysql
  • rabbitmq

Actuellement pris en charge mysql Base de données,Mais la composante accès aux données utilise freesql Il est donc facile de prendre en charge d'autres bases de données par la suite..Les services de messagerie fiables actuellement utilisés par le cadre sont: rabbitmq .

Exécuter le serveur

Créer une nouvelle base de données et une nouvelle table dans le Service

// crate event_message table on mysql
create table if not exists event_message
(
	event_id varchar(36) not null
		primary key,
	biz_msg varchar(4000) null,
	status enum('Prepare', 'Done', 'WaitSend', 'Sent', 'Finish', 'Cancel') not null,
	create_time datetime(3) null,
	event_name varchar(255) null
);

Utiliserdocker-composeExécuter le serveur

version: "3"  # optional since v1.27.0
services:
  agile_dt:
    image: "kklldog/agile_dt"
    ports:
      - "5000:5000"
    environment:
      - db:provider=mysql
      - db:conn= Database=agile_dt;Data Source=192.168.0.115;User Id=root;Password=mdsd;port=3306
      - mq:userName=admin
      - mq:password=123456
      - mq:host=192.168.0.115
      - mq:port=5672

Installer un client

Doit être installé à la fois sur le côté actif et sur le côté passifAgileDTBibliothèque client pour

Install-Package AgileDT.Client

Méthode d'utilisation de l'initiateur

  1. Ajouter une table de messages de transaction à la base de données des entreprises
// crate event_message table on mysql
create table if not exists event_message
(
	event_id varchar(36) not null
		primary key,
	biz_msg varchar(4000) null,
	status enum('Prepare', 'Done', 'WaitSend', 'Sent', 'Finish', 'Cancel') not null,
	create_time datetime(3) null,
	event_name varchar(255) null
);

  1. Modifier le profil
Inappsettings.jsonLe fichier ajoute le noeud suivant:
  "agiledt": {
    "server": "http://localhost:5000",
    "db": {
      "provider": "mysql",
      "conn": "Database=agile_order;Data Source=192.168.0.125;User Id=dev;Password=dev@123f;port=13306"
      //"conn": "Database=agile_order;Data Source=192.168.0.115;User Id=root;Password=mdsd;port=3306"
    },
    "mq": {
      "host": "192.168.0.125",
      //"host": "192.168.0.115",
      "userName": "admin",
      "password": "123456",
      "port": 5672
    }
  }
  1. Injection AgileDT Services à la clientèle
       public void ConfigureServices(IServiceCollection services)
        {
            services.AddAgileDT();
            ...
        }
  1. RéalisationIEventServiceMéthodes
    La classe qui gère la logique opérationnelle de l'initiative doit être mise en œuvreIEventServiceInterface,Et marquer cette méthode est la vraie méthode d'affaires.AgileDTCes types sont scannés au démarrage,Et utiliserAOPClasse d'agent de génération de technologie,Insérer la logique correspondante avant et après la méthode d'affaires pour communiquer avec un service de messagerie fiable.
    Quelques points à noter ici:
  • RéalisationIEventServiceInterface
  • UtiliserDtEventBizMethodAnnotation Tag Business entry Method
  • UtiliserDtEventNameNom de la méthode annotée pour marquer la transaction,Utiliser le nom de la classe s'il n'est pas marqué

Attention!:Les méthodes d'affaires doivent éventuellement utiliser des transactions pour synchroniser la modification d'une table de messagesstatusLe champ estdoneStatut,Ce cadre opérationnel ne vous aidera pas à le mettre en œuvre.
Attention!:Si la méthode d'affaires échoue, lancez - la.Exception,L'exécution est considérée comme réussie si le cadre d'exception n'est pas lancé.

 public interface IAddOrderService:IEventService
    {
        bool AddOrder(Order order);
    }

    [DtEventName("orderservice.order_added")]
    public class AddOrderService : IAddOrderService
    {
        private readonly ILogger<AddOrderService> _logger;

        public AddOrderService(ILogger<AddOrderService> logger)
        {
            _logger = logger;
        }

        public string EventId { 
            get;
            set;
        }
        
        [DtEventBizMethod]
        public virtual bool AddOrder(Order order)
        {
            var ret = false;

            //3. Écris. Order Suivez - moi. Modifier event L'état de doit être écrit dans la même transaction
            FreeSQL.Instance.Ado.Transaction(() =>
            {
                order.EventId = EventId;//Ajouter un nouveau formulaire de commandeeventidChamp,FaireorderSuivez - moi.event_messageTableaux liés
                var ret0 = FreeSQL.Instance.Insert(order).ExecuteAffrows();
                var ret1 = FreeSQL.Instance.Update<OrderService.Data.entities.EventMessage>()
                .Set(x => x.Status, MessageStatus.Done)
                .Where(x => x.EventId == EventId)
                .ExecuteAffrows();

                ret = ret0 > 0 && ret1 > 0;
            });

            return ret;

        }

        /// <summary>
        /// Construire le contenu du message nécessaire au traitement ultérieur des affaires
        /// </summary>
        /// <returns></returns>
        public string GetBizMsg()
        {
            //Ici, vous pouvez construire le passage àMQContenu du message d'affaires pour,Comme le numéro d'ordre de livraison. ,Utilisé par les parties passives suivantes lors du traitement des affaires
            var order = FreeSQL.Instance.Select<Order>().Where(x => x.EventId == EventId).First();
            return order?.Id;
        }
      
    }

On y arrive. IAddOrderService Après l'interface,Vous pouvez l'utiliser comme d'habitude IAddOrderService Pour injecter des classes d'implémentation.Comme dans Controller Le constructeur de.Parce que AgileDT Vous serez automatiquement enregistré au démarrage.

Attention!:IAddOrderService Et le cycle de vie de la classe d'implémentation est Scoped .

Méthode d'utilisation passive

  1. Créer une table dans la base de données de l'entreprise ou ajouter des champs à la table de l'entreprise
    Il n'est pas nécessaire de construire une table pour un passif.Mais il faut au moins un endroit pour le stocker.event_idInformations sur,Le plus simple est d'ajouter directement au tableau principal de l'entrepriseevent_idChamp.
  2. Modifier le profil
Inappsettings.jsonLe fichier ajoute le noeud suivant:
  "agiledt": {
    "server": "http://localhost:5000",
    "db": {
      "provider": "mysql",
      "conn": "Database=agile_order;Data Source=192.168.0.125;User Id=dev;Password=dev@123f;port=13306"
      //"conn": "Database=agile_order;Data Source=192.168.0.115;User Id=root;Password=mdsd;port=3306"
    },
    "mq": {
      "host": "192.168.0.125",
      //"host": "192.168.0.115",
      "userName": "admin",
      "password": "123456",
      "port": 5672
    }
  }
  1. InjectionAgileDTServices
       public void ConfigureServices(IServiceCollection services)
        {
            services.AddAgileDT();
            ...
        }
  1. RéalisationIEventMessageHandlerInterface
    La partie passive doit recevoirMQMessage envoyé,Ces classes de traitement doivent être mises en œuvreIEventMessageHandlerInterface.AgileDTScanne ces classes au démarrage,Et suivreMQÉtablir une relation de liaison.
  • Doit être utilisé iciDtEventNameAnnotation Tag nom de l'événement à traiter
  • Reveive La méthode doit être invisible.
    public interface IOrderAddedMessageHandler: IEventMessageHandler
    {
    }
    
    [DtEventName("orderservice.order_added")]
    public class OrderAddedMessageHandler: IOrderAddedMessageHandler
    {
        static object _lock = new object();

        public bool Receive(EventMessage message)
        {
            var bizMsg = message.BizMsg;
            var eventId = message.EventId;
            string orderId = bizMsg;

            lock (_lock)
            {
                var entity = FreeSQL.Instance.Select<PointHistory>().Where(x => x.EventId == eventId).First();
                if (entity == null)
                {
                    var ret = FreeSQL.Instance.Insert(new PointHistory
                    {
                        Id = Guid.NewGuid().ToString(),
                        EventId = message.EventId,
                        OrderId = orderId,
                        Points = 20,
                        CreateTime = DateTime.Now
                    }).ExecuteAffrows();

                    return ret > 0;
                }
                else
                {
                    return true;
                }
            }
        }
    }

Résumé

Par la démonstration ci - dessus,Nous avons rapidement mis en œuvre un service de points gratuits pour les membres qui passent des commandes.Vous pouvez voir l'utilisation AgileDT Peut rapidement mettre en œuvre une transaction distribuée.Surtout après la mise en œuvre d'une transaction distribuée,C'est très simple à mettre en œuvre.,Il suffit d'implémenter quelques interfaces.AgileDT Ça vient de commencer,J'espère que tout le monde soutiendra,Dodo ,Dodo PR .

https://github.com/kklldog/AgileDT

版权声明
本文为[Agile. Zhou]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/10/20211014052421498a.html

随机推荐