Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Récepteurs ayant fait l'objet de transactions
La principale différence entre les récepteurs transactionnels et les récepteurs non transactionnels est que les récepteurs transactionnels créent et utilisent une transaction MSDTC explicite pour garantir l'atomicité entre leur source de données et la base de données BizTalk Server MessageBox. En général, tous les autres aspects de l’adaptateur sont les mêmes.
Il convient de noter qu’un adaptateur de réception de demande-réponse utilise uniquement une transaction pour envoyer le message de demande d’origine au moteur de messagerie. Une autre transaction est nécessaire pour la transmission de la réponse envoyée du moteur de messagerie à l’adaptateur. Cela est dû au fait que l’étendue de la première transaction est comprise entre l’adaptateur et la base de données MessageBox. Le message de requête suivant n’est pas envoyé à l’adaptateur à partir du moteur de messagerie tant que la transaction pour le message de demande d’origine n’est pas validée.
Le diagramme d’interaction d’objet suivant illustre l’interaction entre l’adaptateur et le moteur de messagerie lors d’une soumission transactionnelle de messages entrants. Dans cet exemple, la séquence d’interactions suivante a lieu :
L’adaptateur reçoit un nouveau lot depuis le moteur.
L’adaptateur crée une transaction MSDTC.
L’adaptateur effectue une lecture destructrice à partir de sa source de données qui a été inscrite dans la transaction.
L’adaptateur envoie le message.
L’adaptateur appelle Terminé sur le lot, transmettant sa transaction MSDTC et le pointeur de rappel BatchComplete. Le moteur retourne une interface IBTDTCCommitConfirm .
Le moteur traite le lot, appelle l’adaptateur sur son implémentation BatchComplete et transmet à l’adaptateur l’état du traitement de ses messages.
Si le lot réussit, l’adaptateur valide la transaction et appelle l’API IBTDTCCommitConfirm.DTCCommitConfirm avec une valeur signifiant la
true
validation.
Émetteurs transactionnés
Les adaptateurs transactionnés sont pour la plupart très similaires aux adaptateurs non transactionnés. La principale différence est que l’adaptateur transactionnel envoie les données dans le message à une ressource qu’il a inscrite dans une transaction MSDTC.
Conseil d’implémentation : Pour les envois transactionnels, l’adaptateur doit utiliser la même transaction MSDTC pour écrire les données dans la destination et pour la supprimer via l’appel de méthode IBTTransportBatch.DeleteMessage . Seules ces deux opérations doivent être traitées. Toutes les autres opérations, telles que IBTTransportBatch.Resubmit, IBTTransportBatch.MoveToNextTransport et IBTTransportBatch.MoveToSuspendQ , n’ont pas besoin d’être traitées. Cela est dû au fait que le moteur utilise implicitement une transaction et que ces types d’opérations n’ont pas besoin d’être atomiques par rapport à la destination.
Le diagramme d’interaction d’objet suivant illustre les interactions entre l’adaptateur et le moteur. La séquence d’événements est la suivante :
Le moteur reçoit un nouveau lot de l’adaptateur.
Le moteur ajoute deux messages au nouveau lot.
Le moteur appelle Terminé sur le lot, ce qui amène l'adaptateur à ajouter le lot à sa file d'attente de transmission interne qui est gérée par son pool de threads.
L’adaptateur crée une transaction MSDTC.
L’adaptateur transmet les messages enrôlant la destination dans la transaction MSDTC. Par exemple, il peut s’agir d’écrire dans une base de données SQL Server.
Après la transmission, l’adaptateur obtient un nouveau lot à partir du moteur.
L’adaptateur appelle DeleteMessage pour les messages qu’il a transmis avec succès.
L'adaptateur appelle Terminé sur le lot de données en y passant sa transaction DTC. Le moteur retourne une interface IBTDTCCommitConfirm .
Le moteur traite le lot et supprime les messages de la file d'attente de l'application.
Le moteur rappelle l’interface IBTBatchCallback de l’adaptateur avec des informations sur la réussite de ses opérations de suppression.
Si le lot a réussi, l’adaptateur valide les transactions.
L’adaptateur appelle IBTDTCCommitConfirm.DTCCommitConfirm pour informer le moteur que la transaction a été validée avec succès.
Adaptateurs transigés Solicit-Response
Contrairement aux réceptions bidirectionnelles, les envois bidirectionnels peuvent être effectués à l’aide de la même transaction DTC. Les adaptateurs de sollicitations-réponses transactionnelles doivent utiliser le même IBTTransportBatch pour les opérations SubmitResponseMessage et DeleteMessage. Ce lot doit utiliser la même transaction MSDTC utilisée pour envoyer et recevoir la paire de messages de demande-réponse. Cela garantit l’atomicité pour l’échange de messages de sollicitation-réponse.
Composants de service et BYOT
Les API du moteur de messagerie nécessitent qu'une transaction MSDTC soit fournie. Toutefois, certains composants .NET sont conçus pour être utilisés en tant que composants service et n’autorisent pas la transaction à être validée par programmation ou abandonnée. Au lieu de cela, la transaction est validée automatiquement par le runtime COM+ sur cette plateforme.
Pour ces scénarios, l’adaptateur doit utiliser Bring Your Own Transaction (BYOT). Cela permet à l’adaptateur de créer une transaction MSDTC, d’instancier le composant .NET qui utilise la transaction et d’autoriser ce composant à hériter de la transaction créée plutôt que de créer sa propre transaction. Le .NET Framework fournit System.EnterpriseServices.BYOT à cet effet. Le Kit de développement logiciel (SDK) BaseAdapter fournit une classe d’assistance , BYOTTransaction, à cet effet.
Éviter les conditions de course
Lorsque vous écrivez un adaptateur qui crée un objet transactionnel et le remet à BizTalk Server, vous acceptez la responsabilité d’écrire du code qui effectue les opérations suivantes :
Résout les erreurs dans les messages associés au lot.
Détermine le résultat final de la transaction associée à l’opération de traitement par lots.
L’adaptateur doit informer BizTalk Server sur le résultat final de la transaction pour conserver ses données de suivi interne. L’adaptateur informe BizTalk Server du résultat en appelant DTCConfirmCommit. Si l’adaptateur ne le fait pas, une fuite de mémoire importante se produit.
Les deux tâches répertoriées ci-dessus (résoudre les erreurs et décider du résultat final) semblent assez simples, mais en fait, elles s’appuient sur des informations provenant de différents threads :
L’adaptateur traite les erreurs en fonction des informations transmises par BizTalk Server via le rappel BatchComplete de l’adaptateur. Cette callback est dans le thread de l’adaptateur.
DTCConfirmCommit est une méthode sur l’objet IBTDTCCommitConfirm . Une instance de l’objet IBTDTCCommitConfirm est retournée par l'appel du lot IBTTransportBatch::Done. Cette instance se trouve sur le même thread que l'appel IBTTransportBatch::Done, ce qui est différent du thread de l'adaptateur.
Pour chaque appel que l’adaptateur effectue à IBTTransportBatch::Done, il existe un retour d'appel correspondant, BatchComplete, appelé par le moteur de messagerie dans un thread distinct afin de signaler le résultat de la soumission du lot. Dans BatchComplete, l'adaptateur doit valider ou annuler la transaction en fonction du succès ou de l'échec du lot. Dans les deux cas, l’adaptateur doit ensuite appeler DTCConfirmCommit pour signaler l’état de la transaction au moteur de messagerie.
Une condition de concurrence possible existe, car l'implémentation de BatchComplete de l'adaptateur peut supposer que l'objet IBTDTCCommitConfirm retourné par IBTTransportBatch::Done est toujours disponible lorsque BatchComplete s'exécute. Toutefois, BatchComplete peut être appelé dans un thread de moteur de messagerie distinct, même avant que IBTTransportBatch::Done retourne. Il est possible que lorsque l’adaptateur tente d’accéder à l’objet IBTDTCCommitConfirm dans le cadre de l’implémentation BatchComplete , il existe une violation d’accès.
Le problème est résolu avec un événement dans l’exemple suivant. Ici, le pointeur d’interface est accessible via une propriété qui utilise l’événement. L’obtention attend toujours le jeu.
protected IBTDTCCommitConfirm CommitConfirm
{
set
{
this.commitConfirm = value;
this.commitConfirmEvent.Set();
}
get
{
this.commitConfirmEvent.WaitOne();
return this.commitConfirm;
}
}
protected IBTDTCCommitConfirm commitConfirm = null;
private ManualResetEvent commitConfirmEvent = new ManualResetEvent(false);
Affectez maintenant la valeur de retour de IBTTransportBatch::Done à cette propriété et utilisez-la dans l’appel BatchComplete.