Condividi tramite


Batch di messaggi per l'elaborazione della ricezione

Richiamate di batch

I batch inviati dagli adapter di ricezione al motore di messaggistica vengono elaborati in modo asincrono. L'adapter necessita, quindi, di un meccanismo con cui legare una richiamata a uno stato dell'adapter, in modo da essere a conoscenza di eventuali errori e poter eseguire le azioni di pulitura necessarie. La semantica della richiamata è flessibile e gli adapter possono utilizzare uno o più approcci. Si tratta di:

  • Tutti i callback vengono eseguiti nella stessa istanza dell'oggetto che implementa IBTBatchCallBack.

  • Il cookie passato al motore quando viene richiesto un nuovo batch viene utilizzato per mettere in relazione la chiamata con lo stato negli adapter.

  • Per ogni batch è disponibile un oggetto callback diverso che implementa IBTBatchCallBack. Ogni oggetto ha un proprio stato privato.

    Quando il batch è stato elaborato, l'adapter viene richiamato nell'implementazione di IBTBatchCallBack.BatchComplete. Lo stato generale del batch è indicato dal primo parametro, HRESULT. Se questo valore è maggiore o uguale a zero, per il batch non si sono verificati errori nel senso che il motore ha la proprietà dei dati e l'adapter è libero di eliminare i dati dal collegamento. Uno stato negativo indica che il batch non è riuscito: nessuna delle operazioni nel batch ha avuto esito positivo e l'adattatore è responsabile della gestione dell'errore.

    Se per il batch si sono verificati errori, l'adapter deve sapere quale elemento in quale operazione ha causato gli errori. Si supponga, ad esempio, che l'adapter abbia letto 20 file dal disco e li invii in BizTalk Server usando un singolo batch. Se il decimo file è stato danneggiato, l'adapter dovrà sospendere tale file e inviare nuovamente il rimanente 19. Queste informazioni sono disponibili per l'adapter nel secondo e nel terzo parametro:opCount (conteggio operazioni) di tipo short e operationStatus, che è di tipo BTBatchOperationStatus[].

Nota

Un messaggio non deve mai essere inviato più di una volta in uno stesso oggetto batch. Se si invia lo stesso oggetto messaggio più volte nello stesso batch vengono generati errori a livello di motore.

Il conteggio delle operazioni indica il numero di tipi di operazioni presenti nel batch (le dimensioni della matrice BTBatchOperationStatus ). Ogni elemento della matrice corrisponde a un determinato tipo di operazione. Usando la matrice BTBatchOperationStatus, l'adapter può determinare l'elemento in un'operazione specificata non riuscita esaminando la matrice BTBatchOperationStatus.MessageStatus per i valori HRESULT negativi che indicano un errore. Nel precedente scenario, l'adapter crea uno nuovo batch contenente 19 invii di messaggi e la sospensione di un messaggio.

Nel seguente frammento di codice viene illustrato in che modo un adapter richiede un nuovo batch al motore tramite il proxy di trasporto e invia un solo messaggio al motore utilizzando il meccanismo dei cookie. Il motore di messaggistica chiama il metodo BatchComplete come callback batch al termine dell'elaborazione dell'intero batch di messaggi inviati.

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

L'SDK di BizTalk Server include esempi per gli adattatori seguenti: File, HTTP, MSMQ e Adapter transazionale. Tutti questi adapter si basano su un blocco predefinito comune denominato BaseAdapter. La versione 1.0.1 di BaseAdapter contiene tutto il codice necessario per analizzare lo stato dell'operazione e rigenerare un nuovo batch da inviare.

Race condition

Le due attività di risoluzione degli errori e di decisione del risultato finale di un batch inviato sembrano alquanto semplici, ma in realtà si basano su informazioni fornite da thread diversi:

  • L'adapter elabora gli errori in base alle informazioni passate da BizTalk Server al metodo di callback di BatchComplete dell'adattatore. Questa richiamata viene eseguita sul thread dell'adapter.

  • DTCCommitConfirm è un metodo nell'oggetto IBTDTCCommitConfirm . Un'istanza dell'oggetto IBTDTCCommitConfirm viene restituita dalla chiamata batch IBTTransportBatch::D one . Questa istanza si trova nello stesso thread della chiamata IBTTransportBatch::D one , diversa dal thread di callback dell'adapter.

    Per ogni chiamata eseguita dall'adapter a IBTTransportBatch::D one il motore di messaggistica effettua una chiamata corrispondente al metodo di callback BatchComplete in un thread separato per segnalare il risultato dell'invio batch. In BatchComplete l'adapter deve eseguire il commit o il rollback della transazione in base al fatto che il batch sia passato o non riuscito. In entrambi i casi, l'adapter deve quindi chiamare DTCCommitConfirm per segnalare lo stato della transazione.

    Esiste una condizione di gara possibile perché l'implementazione dell'adapter di BatchComplete può presumere che l'oggetto IBTDTCCommitConfirm restituito da IBTTransportBatch::D one sia sempre disponibile quando BatchComplete viene eseguito. Tuttavia, BatchComplete può essere chiamato in un thread del motore di messaggistica separato, anche prima che IBTTransportBatch::D one restituisca. È possibile che quando l'adapter tenta di accedere all'oggetto IBTDTCCommitConfirm come parte dell'implementazione di BatchComplete , esiste una violazione di accesso perché il thread chiamante non esiste più. Per evitare questo problema, utilizzare la seguente soluzione.

    Nel seguente esempio il problema viene risolto utilizzando un evento. In questo caso, l'accesso al puntatore dell'interfaccia avviene tramite una proprietà che utilizza l'evento. Get attende sempre il completamento di set prima di proseguire.

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

Codici di stato del batch

Il codice di stato generale del batch indica l'esito del batch. Lo stato dell'operazione fornisce il codice di stato per l'invio dei singoli messaggi. Gli errori dei batch possono essere dovuti a vari motivi. Potrebbe essersi verificato un problema relativo alla protezione oppure il messaggio potrebbe essere stato inviato mentre era in corso l'arresto del motore. In genere quando il motore si arresta non accetta alcun nuovo lavoro, ma consente il completamento del lavoro in-process. La tabella seguente indica alcuni valori HRESULT comuni restituiti nello stato batch o nello stato dell'operazione. Viene specificato, inoltre, se i codici indicano una situazione di errore o meno. La corretta gestione di questi codici è descritta più completamente in Come gestire gli errori dell'adattatore.

Codice (definito nella classe BTTransportProxy) Esito positivo o esito negativo Descrizione
BTS_S_EPM_SECURITY_CHECK_FAILED Operazione completata La porta è stata configurata per eseguire un controllo della protezione ed elimina i messaggi che non superano l'autenticazione. Gli adapter non devono sospendere i batch che restituiscono questo codice di stato.
BTS_S_EPM_MESSAGE_SUSPENDED Operazione completata Indica che uno o più messaggi sono stati sospesi e che il motore è proprietario dei dati. L'esito è positivo nel senso che il motore di messaggistica ha accettato l'invio dei messaggi.
E_BTS_URL_DISALLOWED Operazioni non riuscite Un messaggio è stato inviato con un inboundTransportLocation non valido.

Operazioni batch

Nella tabella seguente vengono descritti i metodi e le operazioni membro dell'oggetto IBTTransportBatch usato dall'adapter per aggiungere il lavoro a un determinato batch.

Nome metodo Tipo di operazione Descrizione
SubmitMessage Invia Invia un messaggio al motore.
SubmitResponseMessage Invia Invia un messaggio di risposta al motore. È il messaggio di risposta in una coppia sollecitazione-risposta.
DeleteMessage Delete Elimina un messaggio che un adapter ha trasmesso utilizzando un invio non bloccante. Gli adattatori che usano i messaggi di blocco non devono chiamare questo metodo perché il motore di messaggistica lo eliminerà per conto dell'adattatore se l'adapter restituisce trueda TransmitMesssage.
MoveToSuspendQ MoveToSuspendQ Sposta il messaggio nella coda degli elementi sospesi.
Inviare Resubmit Richiede che venga tentata di nuovo la trasmissione di un messaggio in un momento successivo. Di norma questo metodo viene chiamato dopo un tentativo di trasmissione non riuscito.
MoveToNextTransport MoveToNextTransport Richiede che un messaggio venga trasmesso utilizzando il trasporto di backup. Di norma viene chiamato al termine di tutti i tentativi. In assenza di un trasporto di backup il metodo ha esito negativo.
SubmitRequestMessage Invio richiesta Invia un messaggio di richiesta. È il messaggio di richiesta in una coppia richiesta-risposta.
CancelRequestForResponse CancelRequestForResponse Comunica al motore che l'adapter non desidera più attendere il messaggio di risposta in una coppia richiesta-risposta.
Cancella ND Cancella tutto il lavoro dal batch.
Completato ND Invia un batch di messaggi al motore di messaggistica per l'elaborazione

Gestione di Batch

I batch vengono implementati in codice nativo nel motore di messaggistica. Per questo motivo un adapter scritto in codice gestito deve rilasciare il Runtime Callable Wrapper (RCW) per il batch dopo aver completato il batch. Questa operazione viene eseguita nel codice gestito usando l'API Marshallal.ReleaseComObject . È importante ricordare che questa API deve essere chiamata in un ciclo while finché il numero di riferimenti restituiti non è zero.

BizTalk Server elabora i messaggi in modo sincrono all'interno di un batch. È possibile elaborare simultaneamente molti batch e questo offre l'opportunità di ottenere una certa ottimizzazione nell'adapter regolando le dimensioni dei batch nel dominio dell'applicazione. Si potrebbe, ad esempio, elaborare tutti i file in un sito FTP (fino al raggiungimento di un certo limite). Nel caso di SAP si potrebbe elaborare un solo flusso in un numero di messaggi che vengono quindi inviati come batch.

Il batch usato da un adattatore per passare le operazioni a BizTalk Server non deve corrispondere esattamente all'elenco di messaggi che BizTalk Server dà all'adattatore. In altre parole, quando si esegue l'operazione transazionale, è necessario suddividere le operazioni di resubmit MoveToNextTransport e MoveToSuspendQ in batch separati. Molti adapter ordinano un batch di messaggi che sono stati inviati per più endpoint in elenchi distinti di messaggi.

Il punto è che non sono presenti regole (oltre a quelle associate alla transazione) associate al batch di messaggi in BizTalk Server. Il batch è semplicemente un modo specifico per l'implementazione dell'adattatore per blocchi di messaggi in e fuori BizTalk Server.

Un adattatore può eseguire il batch di messaggi da più batch più piccoli che BizTalk Server l'ha dato in un batch più grande per la risposta a BizTalk Server. Ciò può rappresentare un'importante ottimizzazione negli adapter transazionali che trattano un numero elevato di messaggi molto piccoli. Infatti viene ridotto al minimo il "numero totale di transazioni per messaggio".

In genere BizTalk Server produce batch lato invio di tra 5 e 10 messaggi. Se questi sono messaggi molto piccoli, un adattatore potrebbe eseguire il batch fino a 100 messaggi o più prima di inviare un batch transazionale di eliminazioni a BizTalk Server. Un'ottimizzazione come questa non è facile da implementare. È necessario controllare che i messaggi non rimangano mai bloccati nella memoria dell'adapter, nell'attesa infinita che venga raggiunta una qualche soglia.

Il significato del batch può essere visto nei numeri di prestazioni per BizTalk Server per le schede a velocità effettiva elevata come MQSeries. In questi adapter i messaggi vengono ricevuti almeno due volte più spesso di quanto vengano inviati. Per impostazione predefinita, l'adattatore di ricezione usa batch di 100 messaggi e l'adattatore di invio usa il batch predefinito BizTalk Server specificato.

Batch transazionali

Quando si scrive un adattatore che crea un oggetto transazione e lo passa a BizTalk Server, si accetta la responsabilità di scrivere codice che esegue le operazioni seguenti:

  • Decide il risultato finale dell'operazione batch: per eseguire il commit o terminare la transazione. Ciò può dipendere da altri rami transazionali all'interno dell'ambito di questa transazione che non sono BizTalk Server dipendenti, ad esempio la scrittura in una coda di accodamento messaggi (MSMQ) o un'operazione di database transazionale.

  • Informa BizTalk Server del risultato finale chiamando il metodo IBTDTCCommitConfirm.DTCCommitConfirmConfirm. La restituzione true indica un commit riuscito della transazione. La restituzione false indica l'errore e il rollback della transazione.

    L'adattatore deve informare BizTalk Server sul risultato finale della transazione per mantenere i dati di rilevamento interni. L'adapter informa BizTalk Server del risultato chiamando DTCCommitConfirm. Se l'adapter non lo fa, si verifica un'importante perdita di memoria, potrebbe verificarsi il time-out della transazione MSDTC e la transazione potrebbe avere esito negativo indipendentemente dal fatto che le sue operazioni siano state completate senza problemi.