Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Llamadas en Lote
Los lotes enviados por adaptadores de recepción al motor de mensajería se procesan de forma asincrónica. Por lo tanto, el adaptador necesita un mecanismo para vincular una devolución de llamada a algún estado en el adaptador para que pueda recibir notificaciones de éxito o error y realizar las acciones de limpieza necesarias. La semántica de devolución de llamada es flexible para que los adaptadores puedan usar uno de los tres enfoques o una combinación de ellos. Estos son:
Todas las devoluciones de llamada se realizan en la misma instancia del objeto que implementa IBTBatchCallBack.
La cookie que se pasa al motor al solicitar un nuevo lote se utiliza para correlacionar el callback con el estado en los adaptadores.
Hay un objeto de retorno de llamada diferente para cada lote que implementa IBTBatchCallBack. Aquí cada objeto contiene su propio estado privado.
Una vez procesado el lote, se llama nuevamente al adaptador mediante su implementación de IBTBatchCallBack.BatchComplete. El estado general del lote se indica mediante el primer parámetro, el estado HRESULT. Si este valor es mayor o igual que cero, el lote se realizó correctamente, lo que significa que el motor de procesamiento tiene la propiedad de los datos y el adaptador puede eliminar dichos datos de la conexión. Un estado negativo indica que se produjo un error en el lote: ninguna de las operaciones del lote se realizó correctamente y el adaptador es responsable de controlar el error.
Si se produjo un error en el lote, el adaptador debe saber qué elemento en qué operación se produjo un error. Por ejemplo, supongamos que el adaptador estaba leyendo 20 archivos del disco y enviarlos a BizTalk Server mediante un único lote. Si el décimo archivo estaba dañado, el adaptador tendría que suspender ese archivo y volver a enviar el resto de 19. Esta información está disponible para el adaptador en los parámetros segundo y tercero:
opCount
(recuento de operaciones) de tipo short yoperationStatus
, que es de tipo BTBatchOperationStatus[].
Nota:
En un único objeto por lotes, nunca debe enviar un mensaje más de una vez. Si se envía el mismo objeto de mensaje más de una vez en el mismo lote, se producirán errores en el motor.
El recuento de operaciones indica cuántos tipos de operaciones estaban en el lote (el tamaño de la matriz BTBatchOperationStatus ). Cada elemento de la matriz de estado de la operación corresponde a un tipo de operación determinado. Mediante el uso de la matriz BTBatchOperationStatus , el adaptador puede determinar qué elemento de una operación determinada produjo un error examinando la matriz BTBatchOperationStatus.MessageStatus para detectar un error negativo en los valores HRESULT. En el escenario anterior, el adaptador crea un nuevo lote que contiene 19 envíos de mensajes y una suspensión de mensajes.
En el fragmento de código siguiente se muestra cómo un adaptador solicita un nuevo lote desde el motor a través de su proxy de transporte y envía un único mensaje al motor mediante el enfoque de cookies. El motor de mensajería llama al método BatchComplete como devolución por lotes cuando se ha completado el procesamiento completo del lote de mensajes enviados.
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);
}
}
El SDK de BizTalk Server incluye ejemplos para los siguientes adaptadores: File, HTTP, MSMQ y Transactional Adapter. Todos estos adaptadores se basan en un bloque de creación común denominado BaseAdapter. La versión 1.0.1 de BaseAdapter incluye todo el código pertinente para analizar el estado de la operación y recompilar un nuevo lote que se va a enviar.
Condición de carrera
Las dos tareas de resolver errores y decidir el resultado final de un lote enviado parecen lo suficientemente simples, pero de hecho se basan en información de diferentes subprocesos:
El adaptador procesa errores en función de la información pasada por BizTalk Server al método de devolución de llamada BatchComplete del adaptador. Este callback se ejecuta en el hilo del adaptador.
DTCCommitConfirm es un método en el objeto IBTDTCCommitConfirm . La llamada IBTTransportBatch::Done devuelve una instancia del objeto IBTDTCCommitConfirm. Esta instancia está en el mismo subproceso que la llamada IBTTransportBatch::Done, que es diferente del subproceso de devolución de llamada del adaptador.
Por cada llamada que realiza el adaptador a IBTTransportBatch::Done, el motor de mensajería realiza una llamada correspondiente al método de devolución de llamada BatchComplete en un subproceso independiente para notificar el resultado del envío por lotes. En BatchComplete, el adaptador debe confirmar o revertir la transacción según si el lote ha pasado o fallado. En cualquier caso, el adaptador debe llamar a DTCCommitConfirm para notificar el estado de la transacción.
Existe una posible condición de carrera porque la implementación del adaptador de BatchComplete puede suponer que el objeto IBTDTCCommitConfirm devuelto por IBTTransportBatch::Done siempre está disponible cuando BatchComplete se ejecuta. Sin embargo, se puede invocar a BatchComplete en un subproceso independiente del motor de mensajería, incluso antes de que IBTTransportBatch::Done devuelva. Es posible que cuando el adaptador intente acceder al objeto IBTDTCCommitConfirm como parte de la implementación de BatchComplete , hay una infracción de acceso porque ya no existe el subproceso que realiza la llamada. Use la siguiente solución para evitar esta condición.
En el ejemplo siguiente, el problema se resuelve mediante un evento . Aquí se accede al puntero de interfaz a través de una propiedad que usa el evento . La operación de obtención siempre espera a que la configuración se complete antes de continuar.
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);
Códigos de estado de lote
El código de estado general del lote indica el resultado del lote. El estado de la operación proporciona el código de estado de envío para elementos de mensaje individuales. Los lotes pueden fallar por varias razones. Es posible que haya un error relacionado con la seguridad o que el mensaje se haya enviado cuando el motor se apague. (Normalmente, cuando el motor se apaga, no acepta ningún trabajo nuevo, pero permite que se complete el trabajo en proceso). En la tabla siguiente se indican algunos valores HRESULT comunes que se devuelven en el estado del lote o en el estado de la operación. También indica si se trata de códigos correctos o de error. El control adecuado de estos códigos se describe más completamente en Cómo controlar los errores del adaptador.
Código (definido en la clase BTTransportProxy) | Código de éxito o error | Descripción |
---|---|---|
BTS_S_EPM_SECURITY_CHECK_FAILED | Éxito | El puerto se configuró para realizar una comprobación de seguridad y quitar mensajes con errores de autenticación. Los adaptadores no deben suspender lotes que devuelvan este código de estado. |
BTS_S_EPM_MESSAGE_SUSPENDED | Éxito | Indica que se suspendieron uno o más mensajes y que el motor tiene la propiedad de los datos. Es un código de éxito ya que el motor de mensajería ha aceptado el envío del mensaje. |
E_BTS_URL_DISALLOWED | Fracaso | Se envió un mensaje con inboundTransportLocation no válido. |
Operaciones por lotes
En la tabla siguiente se detallan los métodos de miembro y las operaciones del objeto IBTTransportBatch que usa el adaptador para agregar trabajo a un lote determinado.
Nombre del método | Tipo de operación | Descripción |
---|---|---|
SubmitMessage | Enviar | Envía un mensaje al motor. |
SubmitResponseMessage | Enviar | Envía un mensaje de respuesta al motor. Este es el mensaje de respuesta en un par solicitud-respuesta. |
DeleteMessage | Borrar | Elimina un mensaje que un adaptador ha transmitido correctamente por cable mediante un envío sin bloqueo. Los adaptadores que usan envíos de bloqueo no necesitan llamar a este método porque el Motor de Mensajería lo eliminará por el adaptador si el adaptador devuelve true de TransmitMessage. |
MoveToSuspendQ | MoveToSuspendQ | Mueve un mensaje a la cola suspendida. |
Volver a enviar | Volver a enviar | Solicita que se vuelva a intentar enviar un mensaje para su transmisión más tarde. Normalmente se llama a esto después de que se haya producido un error en un intento de transmisión. |
MoveToNextTransport | MoverAlSiguienteTransporte | Solicita transmitir un mensaje mediante su transporte de respaldo. Normalmente se llama después de que se hayan agotado todos los reintentos. Si no hay transporte de copia de seguridad presente, se producirá un error en este método. |
SubmitRequestMessage | EnviarSolicitud | Envía un mensaje de solicitud. Se trata de un mensaje de solicitud dentro de un par solicitud-respuesta. |
CancelRequestForResponse | CancelarSolicitudDeRespuesta | Notifica al motor que el adaptador ya no desea seguir esperando el mensaje de respuesta en una interacción de solicitud-respuesta. |
Claro | NA | Borra todo el trabajo del lote. |
Listo | NA | Envía un lote de mensajes al motor para su procesamiento. |
Administración de lotes
Los lotes se implementan en código nativo en el motor de mensajería. Por este motivo, un adaptador escrito en código administrado debe liberar el contenedor al que se puede llamar en tiempo de ejecución (RCW) para el lote una vez que haya terminado con el lote. Esto se hace en código administrado mediante la API Marshal.ReleaseComObject . Es importante recordar que se debe llamar a esta API en un bucle 'while' hasta que el recuento de referencias devuelto alcance cero.
BizTalk Server procesa mensajes de forma sincrónica dentro de un lote. Muchos lotes se pueden procesar simultáneamente, lo que puede proporcionar una oportunidad para alguna optimización en el adaptador ajustando el tamaño del lote en el dominio de aplicación. Por ejemplo, puede procesar todos los archivos de un sitio FTP (hasta que se alcance algún límite). En el caso de SAP, puede procesar una sola secuencia en una serie de mensajes que, a continuación, se envían como un lote.
El lote usado por un adaptador para devolver operaciones a BizTalk Server no necesita corresponder exactamente a la lista de mensajes que proporciona BizTalk Server al adaptador. En otras palabras, al realizar envíos transaccionales, debe dividir las operaciones de reenvío MoveToNextTransport y MoveToSuspendQ en lotes independientes. Muchos adaptadores ordenan un lote de mensajes que se han enviado para varios puntos de conexión en listas independientes de mensajes para su posterior procesamiento.
El punto es que no hay reglas (además de las asociadas a la transacción) asociadas con el procesamiento por lotes de mensajes en BizTalk Server. El procesamiento por lotes es simplemente una forma específica de la implementación para que el adaptador fragmente los mensajes al entrar y salir de BizTalk Server.
Un adaptador puede agrupar varios lotes pequeños que BizTalk Server le ha proporcionado en un lote mayor para la respuesta a BizTalk Server. Esto puede ser una optimización significativa en los adaptadores transaccionales que se ocupan de un gran número de mensajes muy pequeños. Minimiza la relación "número total de transacciones por mensaje".
Normalmente, BizTalk Server genera lotes de envío de entre 5 y 10 mensajes. Si estos son mensajes muy pequeños, un adaptador puede procesar por lotes hasta 100 mensajes o más antes de enviar un lote transaccional de eliminaciones de nuevo a BizTalk Server. Una optimización como esta no es fácil de implementar; Debe asegurarse de que los mensajes nunca se bloquean en la memoria del adaptador, esperando sin fin para que se cumpla algún umbral.
La importancia del procesamiento por lotes se puede ver en los números de rendimiento de BizTalk Server para los adaptadores de alto rendimiento, como MQSeries. En estos adaptadores, los mensajes se reciben al menos el doble de veces que se envían. De forma predeterminada, el adaptador de recepción usa lotes de 100 mensajes y el adaptador de envío usa el lote predeterminado de BizTalk Server que se proporciona.
Lotes transaccionales
Al escribir un adaptador que crea un objeto de transacción y lo entrega a BizTalk Server, acepta la responsabilidad de escribir código que haga lo siguiente:
Decide el resultado final de la operación por lotes: para confirmar o finalizar la transacción. Esto puede depender de otras ramas transaccionales dentro del ámbito de esta transacción que no dependen de BizTalk Server, como escribir en una cola de Message Queuing (MSMQ) o realizar una operación de base de datos transaccional.
Informa a BizTalk Server del resultado final llamando al método IBTDTCCommitConfirm.DTCCommitConfirm . Devolver
true
indica una confirmación correcta de la transacción; devolverfalse
significa un error y una reversión de la transacción.El adaptador debe informar a BizTalk Server sobre el resultado final de la transacción para mantener sus datos de seguimiento internos. El adaptador informa a BizTalk Server del resultado llamando a DTCCommitConfirm. Si el adaptador no lo hace, se produce una pérdida de memoria significativa y la transacción MSDTC podría agotar el tiempo de espera y producir un error a pesar de que sus operaciones se completaron correctamente.