Partager via


Rassembler les messages pour le traitement de réception

Rappels par lots

Les lots envoyés par les adaptateurs de réception au moteur de messagerie sont traités de manière asynchrone. Par conséquent, l’adaptateur a besoin d’un mécanisme pour lier un rappel à un état dans l’adaptateur afin qu’il puisse être averti de la réussite ou de l’échec et effectuer toutes les actions de nettoyage nécessaires. La sémantique de rappel est flexible afin que les adaptateurs puissent utiliser une ou une combinaison de trois approches. Ces règles sont les suivantes :

  • Tous les rappels sont effectués sur la même instance d’objet qui implémente IBTBatchCallBack.

  • Le cookie passé dans le moteur lors de la demande d’un nouveau lot est utilisé pour mettre en relation le "callback" avec l’état dans les adaptateurs.

  • Il existe un objet de rappel différent pour chaque lot qui implémente IBTBatchCallBack. Ici, chaque objet contient son propre état privé.

    Une fois le traitement du lot effectué, l’adaptateur est appelé de nouveau dans le cadre de son implémentation d’IBTBatchCallBack.BatchComplete. L’état global du lot est indiqué par le premier paramètre, l’état HRESULT. Si cette valeur est supérieure ou égale à zéro, le lot a réussi dans le sens où le moteur possède la propriété des données et que l’adaptateur est libre de supprimer ces données du câble. Un état négatif indique que le lot a échoué : aucune des opérations du lot n’a réussi et l’adaptateur est responsable de la gestion de l’échec.

    Si le lot a échoué, l’adaptateur doit savoir quel élément dans lequel l’opération a échoué. Par exemple, supposons que l’adaptateur lit 20 fichiers à partir du disque et les envoie dans BizTalk Server à l’aide d’un seul lot. Si le dixième fichier a été endommagé, l’adaptateur doit suspendre ce fichier et soumettre à nouveau les 19 restants. Ces informations sont disponibles pour l’adaptateur dans les deuxième et troisième paramètres :opCount (nombre d’opérations) de type court et operationStatus, qui est de type BTBatchOperationStatus[].

Remarque

Sur un seul objet batch, vous ne devez jamais envoyer un message plusieurs fois. L’envoi du même objet de message plusieurs fois sur le même lot entraîne des erreurs de moteur.

Le nombre d’opérations indique le nombre de types d’opérations dans le lot (taille du tableau BTBatchOperationStatus ). Chaque élément du tableau d’état de l’opération correspond à un type d’opération donné. En utilisant le tableau BTBatchOperationStatus , l’adaptateur peut déterminer quel élément dans une opération donnée a échoué en examinant le tableau BTBatchOperationStatus.MessageStatus pour les valeurs HRESULT négatives signifiant l’échec. Dans le scénario ci-dessus, l’adaptateur crée un lot contenant 19 envois de messages et une suspension de message.

Le fragment de code suivant montre comment un adaptateur demande un nouveau lot à partir du moteur via son proxy de transport et envoie un message unique dans le moteur à l’aide de l’approche de cookie. Le moteur de messagerie appelle la méthode BatchComplete comme rappel par lot lorsqu’il a terminé le traitement de l’ensemble du lot de messages envoyés.

using Microsoft.BizTalk.TransportProxy.Interop;  
using Microsoft.BizTalk.Message.Interop;  
  
public class MyAdapter :   
                  IBTTransport,   
                  IBTTransportConfig,   
                  IBTTransportControl,  
                  IPersistPropertyBag,   
                  IBaseComponent,  
                  IBTBatchCallBack  
{  
      private IBTTransportProxy _tp;  
  
      public void BatchComplete(      
            Int32                         status,   
            Int16                         opCount,   
            BTBatchOperationStatus[]      operationStatus,   
            System.Object                 callbackCookie)  
      {  
            // Use cookie to correlate callback with work done,  
            // in this example the batch is to submit a single  
            // file the name of which will be in the  
            // callbackCookie  
            string fileName = (string)callbackCookie;  
            if ( status >= 0 )  
                  // DeleteFile from disc  
                  File.Delete(fileName);          
            else  
                  // Rename file to fileName.bad  
                  File.Move(fileName, fileName + ".bad");  
      }  
  
      private void SubmitMessage(  
            IBaseMessage                  msg,   
            string                        fileName)  
      {  
            // Note: Pass in the filename as the cookie  
            IBTTransportBatch batch =   
                  _tp.GetBatch(this, (object)fileName);  
  
            // Add msg to batch for submitting   
            batch.SubmitMessage(msg);   
  
            // Process this batch  
            batch.Done(null);  
      }  
}  

Le Kit de développement logiciel (SDK) BizTalk Server inclut des exemples pour les adaptateurs suivants : fichier, HTTP, MSMQ et adaptateur transactionnel. Tous ces adaptateurs sont basés sur un bloc de construction commun appelé BaseAdapter. La version 1.0.1 de BaseAdapter inclut tout le code approprié pour analyser l’état de l’opération et reconstruire un nouveau lot à soumettre.

Condition de course

Les deux tâches de résolution des erreurs et de décider du résultat final d’un lot soumis 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 à la méthode de rappel BatchComplete de l’adaptateur. Ce rappel s’exécute sur le thread de l’adaptateur.

  • DTCCommitConfirm 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 rappel de l'adaptateur.

    Pour chaque appel que l’adaptateur effectue à IBTTransportBatch::Done, le moteur de messagerie effectue un appel correspondant à la méthode de rappel BatchComplete dans un thread distinct afin de signaler le résultat de la soumission par 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 DTCCommitConfirm pour signaler l’état de la transaction.

    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, car cet appel de thread n’existe plus. Utilisez la solution suivante pour éviter cette condition.

    Dans l’exemple suivant, le problème est résolu à l’aide d’un événement. Ici, le pointeur d’interface est accessible via une propriété qui utilise l’événement. L’obtention attend toujours que l’ensemble se termine avant de continuer.

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);  

Codes d’état du lot

Le code d’état global du lot indique le résultat du lot. L’état de l’opération donne le code d’état de soumission pour les éléments de message individuels. Les lots peuvent échouer pour différentes raisons. Il peut y avoir une défaillance liée à la sécurité, ou le message a peut-être été envoyé lors de l’arrêt du moteur. (Habituellement, lorsque le moteur s’arrête, il n’accepte aucun nouveau travail mais permet l'achèvement du travail en cours.) Le tableau suivant indique certaines valeurs HRESULT courantes qui sont retournées soit dans l’état du lot, soit dans l’état de l’opération. Il indique également s’il s’agit de codes de réussite ou d’échec. La gestion appropriée de ces codes est décrite plus complètement dans How to Handle Adapter Failures.

Code (défini dans la classe BTTransportProxy) Code de réussite/échec Descriptif
BTS_S_EPM_SECURITY_CHECK_FAILED Succès Le port a été configuré pour effectuer une vérification de sécurité et supprimer les messages qui ont échoué à l'authentification. Les adaptateurs ne doivent pas suspendre les lots qui retournent ce code d’état.
BTS_S_EPM_MESSAGE_SUSPENDED Succès Indique qu’un ou plusieurs messages ont été suspendus et que le moteur possède la propriété des données. Il s’agit d’un code de réussite dans lequel le moteur de messagerie a accepté la soumission du message.
E_BTS_URL_DISALLOWED Échec Un message a été envoyé avec une inboundTransportLocation non valide.

Opérations par lots

Le tableau suivant détaille les méthodes et opérations membres de l’objet IBTTransportBatch que l’adaptateur utilise pour ajouter du travail à un lot donné.

Nom de la méthode Type d'opération Descriptif
SubmitMessage Envoyer Envoie un message dans le moteur.
SubmitResponseMessage Envoyer Envoie un message de réponse dans le moteur. Il s’agit du message de réponse dans une paire de sollicitations-réponse.
DeleteMessage Supprimer Supprime un message que l'adaptateur a transmis avec succès sur le réseau à l’aide d’un envoi non bloquant. Les adaptateurs qui utilisent des envois bloquants n'ont pas besoin d'appeler cette méthode, car le moteur de messagerie le supprimera pour le compte de l’adaptateur si l’adaptateur renvoie true depuis TransmitMessage.
MoveToSuspendQ MoveToSuspendQ Déplace un message dans la file d’attente suspendue.
Resoumettre Resoumettre Demande qu’un message soit retenté pour la transmission ultérieurement. Cela est généralement appelé après l’échec d’une tentative de transmission.
PasserAuTransportSuivant PasserAuTransportSuivant Demande qu’un message soit transmis à l’aide de son transport de sauvegarde. Généralement appelé après que toutes les nouvelles tentatives ont été épuisées. Si aucun transport de sauvegarde n’est présent, cette méthode échoue
SubmitRequestMessage SoumettreDemande Envoie un message de demande. Il s’agit d’un message de requête dans une paire demande-réponse.
CancelRequestForResponse CancelRequestForResponse Avertit le moteur que l’adaptateur ne souhaite plus attendre le message de réponse dans une paire demande-réponse.
Effacer NA Efface tout le travail du lot.
Fait NA Envoie un lot de messages au moteur pour traitement.

Gestion des lots

Les lots sont implémentés dans le code natif au sein du moteur de messagerie. Pour cette raison, un adaptateur écrit dans le code managé doit libérer le wrapper pouvant être appelé au runtime (RCW) pour le lot après l’avoir traité. Cela s’effectue dans le code managé à l’aide de l’API Marshal.ReleaseComObject . Il est important de se rappeler que cette API doit être appelée dans une boucle while jusqu’à ce que le nombre de références retournés atteigne zéro.

BizTalk Server traite les messages de façon synchrone au sein d’un lot. De nombreux lots peuvent être traités simultanément, ce qui peut offrir une possibilité d’optimisation dans l’adaptateur en ajustant la taille du lot dans le domaine d’application. Par exemple, vous pouvez traiter tous les fichiers sur un site FTP (jusqu’à ce qu’une limite soit atteinte). Dans le cas de SAP, vous pouvez traiter un flux unique dans un certain nombre de messages qui sont ensuite envoyés en tant que lot.

Le lot utilisé par un adaptateur pour transmettre des opérations à BizTalk Server n’a pas besoin de correspondre exactement à la liste des messages que BizTalk Server donne à l’adaptateur. En d’autres termes, lorsque vous effectuez des envois transactionnels, vous devez fractionner les opérations de renvoi MoveToNextTransport et MoveToSuspendQ en lots distincts. De nombreux adaptateurs trient un lot de messages qui ont été envoyés pour plusieurs points de terminaison dans des listes distinctes de messages pour un traitement ultérieur.

Le point est qu’il n’existe aucune règle (en plus de celles associées à la transaction) associées au traitement par lots de messages dans BizTalk Server. Le traitement par lots est simplement un moyen spécifique à l’implémentation pour l’adaptateur de segmenter les messages dans et hors de BizTalk Server.

Un adaptateur peut regrouper les messages de plusieurs lots plus petits que lui fournit BizTalk Server dans un lot plus grand pour renvoyer à BizTalk Server. Il peut s’agir d’une optimisation significative dans les adaptateurs transactionnels qui traitent d’un grand nombre de messages très petits. Elle réduit le ratio « nombre total de transactions par message ».

En règle générale, BizTalk Server envoie des lots constitués de 5 à 10 messages. Si ces messages sont très petits, un adaptateur peut traiter jusqu’à 100 messages ou plus avant d’envoyer un lot transactionnel de suppressions à BizTalk Server. Une optimisation comme celle-ci n’est pas facile à implémenter ; vous devez vous assurer que les messages ne sont jamais bloqués dans la mémoire de l’adaptateur, en attendant sans fin que certains seuils soient atteints.

L’importance du traitement par lots est visible dans les numéros de performances de BizTalk Server pour les adaptateurs à débit élevé comme MQSeries. Dans ces adaptateurs, les messages sont reçus au moins deux fois plus souvent qu’ils sont envoyés. Par défaut, l’adaptateur de réception utilise des lots de 100 messages et l’adaptateur d’envoi utilise le lot BizTalk Server par défaut donné.

Lots transactionnels

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 :

  • Détermine le résultat final de l’opération de traitement par lots : pour valider ou mettre fin à la transaction. Cela peut dépendre d’autres branches transactionnelles dans l’étendue de cette transaction qui ne dépendent pas de BizTalk Server, telles que l’écriture dans une file d’attente Message Queuing (MSMQ) ou une opération de base de données transactionnelle.

  • Informe BizTalk Server du résultat final en appelant la méthode IBTDTCCommitConfirm.DTCCommitConfirm. Le retour de true indique une validation réussie de la transaction ; le retour de false signifie l’échec et l’annulation de la transaction.

    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 DTCCommitConfirm. Si l’adaptateur ne le fait pas, une fuite de mémoire importante se produit et la transaction MSDTC peut expirer et échouer malgré les opérations effectuées avec succès.