Cómo controlar errores de adaptador
Por lo general, los adaptadores deberían suspender los mensajes que no pueden procesar. Un adaptador de recepción, por ejemplo, que experimente un error de envío debería suspender los mensajes, aunque esta decisión depende del propósito del adaptador. Además, hay consideraciones de seguridad que se deben tener en cuenta con respecto al control de errores. Si un adaptador, por ejemplo, suspende de forma automática todos los mensajes con errores, es posible que el adaptador esté abierto a un ataque de denegación de servicio que provoque que se llene la cola de suspensión de BizTalk Server. Algunos adaptadores, como HTTP, pueden devolver un código de error al cliente que indique que se ha rechazado la solicitud. Para estos tipos de adaptadores resulta conveniente devolver un código de error en lugar de suspender el mensaje. Como norma general, los adaptadores de envío solo suspenden los mensajes una vez que se han agotado los reintentos tanto para los transportes primarios como los secundarios.
Asociar el procesamiento de errores con una operación individual y no con el lote que contiene la operación
El procesamiento por lotes de los mensajes de un adaptador debería ser invisible al usuario de éste. Esto significa que el error de una operación en un lote no debería afectar en ningún caso a ninguna operación. Sin embargo, los lotes son atómicos con lo que el error de un mensaje provoca un error en el lote y no se procesan las operaciones.
Escriba el código responsable del control de errores, volviendo a enviar los mensajes correctos y suspendiendo los que no lo son. Afortunadamente, BizTalk Server proporciona una estructura de errores detallada que permite al adaptador determinar la operación específica en la que se ha producido el error. Además, permite crear más lotes en los que las operaciones correctas se vuelven a enviar y las que no lo son se suspenden.
El estado final de la operación no debería verse afectado por el procesamiento por lotes del adaptador.
Utilizar SetErrorInfo para informar de los errores a BizTalk Server
Si está suspendiendo un mensaje, debe proporcionar información de los errores a BizTalk Server desde el contexto del mensaje anterior. BizTalk Server proporciona funcionalidades de informes de errores mediante el método SetErrorInfo en las interfaces IBaseMessage e ITransportProxy. Es posible informar de los errores de la siguiente forma:
Cuando se produce un error al procesar un mensaje, establezca la excepción mediante SetErrorInfo(Exception e) en el mensaje (IBaseMessage) que se suspenderá. Esto permite al motor conservar el error con el mensaje para un diagnóstico posterior y registrarlo en el registro de eventos para alertar al administrador.
Si se produce un error durante la inicialización o el mantenimiento interno de libros (no durante el procesamiento de mensajes), debe llamar a SetErrorInfo(Exception e) en el puntero ITransportProxy que se le pasó durante la inicialización. Si el adaptador se basa en la implementación de BaseAdapter, siempre debería tener acceso a este puntero. De lo contrario, debe asegurarse de que lo almacena en la memoria caché.
Al informar de un error mediante alguno de estos métodos, el mensaje de error se escribe en el registro de eventos. Es importante que, siempre que sea posible, se asocie el error con el mensaje relacionado.
Controlar una condición de base de datos sin conexión
Si alguna de las bases de datos de BizTalk Server se desconecta, el servicio de BizTalk se recicla. El motor de mensajería hace lo posible por cerrar todas las ubicaciones de recepción antes de reciclar el servicio. Si este proceso tarda más de 60 segundos, el servicio finaliza. Debido a que se trata de un motor de transacción, no se pierden datos.
Este tiempo de espera puede ajustarse en el Registro mediante la siguiente tecla:
DWORD
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTSSvc{Host Guid}\MessagingDBFailoverShutdownTimeLimit
En el caso de adaptadores aislados, debido a que no es un proceso propio de BizTalk Server, se deshabilitan las ubicaciones de recepción cuando una de las bases de datos de BizTalk Server se desconecta. Las ubicaciones de recepción se habilitan de nuevo una vez que la base de datos se vuelve a conectar.
Escribir en el registro de eventos
El adaptador puede escribir entradas del registro de eventos mediante la interfaz IBTTransportProxy que pasa una excepción. Los adaptadores desarrollados en código nativo deben pasar una interfaz IErrorInfo , IBTTransportProxy.SetErrorInfo( Exceptione
).
El motor de mensajería escribe en el registro de eventos en nombre del adaptador los eventos en los que se da alguno de los siguientes casos: un adaptador vuelve a intentar un mensaje después de un error en la transmisión, mueve un mensaje al transporte de reserva o suspende un mensaje. Para operaciones como las anteriores, el adaptador solo necesita establecer la excepción en el mensaje antes de llamar a la API. En el siguiente fragmento de código se muestra este caso:
IBaseMessage msg;
...
// Set exception on msg to indicate why transmission failed...
msg.SetErrorInfo(
new ApplicationException(
"The TCP connection was closed by the destination"));
Controlar errores de lote específicos de recepciones
Controlar errores de recepción
Cuando un adaptador envía una operación (o un lote de operaciones) a BizTalk Server pueden producirse errores por varias razones. A continuación se indican las dos más importantes:
Error en la canalización de recepción.
Error de enrutamiento mientras se publicaba un mensaje.
El motor de mensajería intenta suspender de forma automática el mensaje cuando se produce un error en la canalización de recepción. Es posible que la operación de suspensión no siempre se ejecute correctamente. Por ejemplo, si el motor de mensajería coincide con un error de enrutamiento mientras se publica un mensaje, no intentará siquiera suspender el mensaje.
Siempre existe la posibilidad de que se produzca un error en un mensaje. En tal situación, el adaptador debe llamar explícitamente a la API MoveToSuspendQ y debe intentar suspender el mensaje. Cuando un adaptador intenta suspender un mensaje, una de las siguientes afirmaciones debería ser verdadera:
Se debería suspender el mismo objeto de mensaje que el adaptador enviado (recomendado).
Si el adaptador tiene que crear un mensaje nuevo, debería establecerse el contexto de mensaje del mensaje nuevo con el puntero como contexto de mensaje del mensaje que se envió en un principio. Esto se debe a que el contexto de mensaje de un mensaje contiene bastante información valiosa acerca del mensaje y del error. Esta información es necesaria para depurar el mensaje con errores.
Nota
Si el adaptador crea un objeto nuevo de mensaje y lo suspende, debería copiar la información del error del objeto anterior del mensaje al nuevo.
Algunos adaptadores, como el HTTP que se proporciona con BizTalk Server, no requieren que se suspenda el mensaje. Estos adaptadores pueden devolver un error a sus equipos cliente.
Causas de error
Las causas simples de error son los errores que se pueden producir cuando se construye el lote o cuando se llama a IBTTransportBatch::D one .
Error de envío. La llamada Submit puede producir un error por un número limitado de motivos y todas ellas son fatales. Estas razones incluyen las siguientes:
Los errores de memoria insuficiente que se producen en el espacio de procesos de BizTalk Server.
El ensamblado de esquema se ha colocado desde la implementación. En este caso, se produce un error críptico en el envío . En el adaptador de MQSeries, se captura la excepción de error genérico de BizTalk Server y se escribe un mensaje de error extendido en el registro de eventos del sistema. Este mensaje sugiere que una de las posibles causas del error es que, de alguna forma, el ensamblado de esquema se ha colocado desde la implementación.
En general, si se produce un error en Submit , debe intentar suspender el mensaje con la misma transacción.
Error IBTTransportBatch::Done. La llamada IBTTransportBatch::D one puede producir un error por uno de varios motivos. Por lo general, debería intentar suspender una operación y finalizar la transacción solo si se producen errores. Uno de los códigos de error que puede recibir del error de IBTTransportBatch::D one es que BizTalk Server está intentando apagarse. En este caso, solo debe finalizar la transacción y dejarlo porque es probable que la llamada a Terminate se produzca simultáneamente. Otros escenarios se producen cuando se ha construido correctamente el lote y se ha ejecutado correctamente IBTTransportBatch::D one. En estos casos, los errores se devuelven en BatchComplete y el adaptador debe determinar qué hacer con ellos. El resto de la sección trata este caso.
Procesamiento de errores BatchComplete
BatchComplete es una devolución de llamada proporcionada por el adaptador invocado por BizTalk Server para indicar el estado de finalización de una operación por lotes.
El parámetro más importante que se pasa a BatchComplete es el estado hResult
del lote . Esto indica si el lote es correcto o contiene errores. Si el lote contiene errores, significa que ninguna de las operaciones que se han realizado en el lote se ha hecho de forma correcta. El adaptador pasa por la estructura de estado del lote y determina qué mensajes han fallado (esto se conoce como filtrado del lote).
Errores BatchComplete no transaccionales
Para adaptadores no transaccionales, debe elegir la respuesta si se produce un error para una operaciónSubmitRequestMessage/ o SubmitResponseMessage. Normalmente, los adaptadores suspenden el mensaje llamando a MoveToSuspendQ.
Siempre se espera que se pasen las siguientes operaciones: DeleteMessage, MoveToSuspendQ, ResubmitMessage. Si se producen errores en estas operaciones, significa, por lo general, que hay un error en el adaptador. En esos casos, no es necesario que escriba código para controlar un error. Sin embargo, si se produce un error en el lote porque hay errores en otra operación, esas operaciones deben volver a ejecutarse en un lote nuevo.
Si el adaptador llama a MovetoBackupTransport y se produce un error (porque no había transporte de copia de seguridad), el adaptador debe llamar a MoveToSuspendQ para suspender el mensaje.
Errores BatchComplete transaccionales
Cuando envía lotes a BizTalk Server mediante una transacción que ha creado el adaptador, debería seguir uno de los dos escenarios siguientes:
Utilizar lotes de mensaje único. Enviar un lote de mensaje único a BizTalk Server. Si se producen errores en ese único mensaje, puede enviar de forma válida un segundo lote a BizTalk Server en la misma transacción pero debe mover el mensaje infractor a la cola de suspensión en lugar de reenviarlo. Una vez que se ha eliminado el mensaje con errores, el envío del segundo lote debería producirse de forma correcta. Cuando esto suceda, puede confirmar la transacción una vez que BizTalk Server confirme que el segundo lote es correcto. Si se producen errores en el segundo lote, el adaptador debe anular la transacción o encontrar otro sitio donde colocar el mensaje. En este escenario, enseguida sufrirá una importante merma en el rendimiento debido al procesamiento de reversión de transacciones.
Para mejorar el rendimiento del adaptador se pueden utilizar algunas técnicas. Por ejemplo, el adaptador de MQSeries ajusta su aproximación de forma dinámica al tiempo de ejecución. Se ejecuta con lotes de 100 mensajes. Si se produce un error, se debe finalizar el lote pero cambia a lotes de mensajes únicos durante un breve período de tiempo cuando pasa por el mensaje malintencionado. A continuación, vuelve a lotes de 100 mensajes. Si se produce el error de nuevo, se vuelve a ralentizar.
Utilizar suspensión preferente. Construir un lote de mensajes múltiples en los que los mensajes erróneos se suspenden de forma preferente. El lote contiene una combinación de operaciones Submit y MoveToSuspendQ , y es el primer y único lote bajo la transacción. Debería realizarse de forma correcta porque los datos no válidos se han suspendido de forma preferente y, además, se puede confirmar la transacción (después de esperar para recibir la confirmación de BizTalk Server).
Puede parecer que sea necesario adelantarse en el futuro, pero esta técnica se ha utilizado en el adaptador de MSMQ. Depende de si se tiene o no identificadores de mensajes únicos confiables. Este adaptador construye un lote de mensajes. Si no se producen errores se revierte la transacción (y, por lo tanto, el lote), pero recuerda el Id. de mensaje en una estructura temporal de datos. (Para evitar que esta estructura crezca indefinidamente, los elementos de ella se quitan después de un retraso de tiempo fijo). Antes de enviar cada lote, el adaptador comprueba la lista de identificadores de mensaje incorrectos. Si ve uno, sabe que se van a producir errores en él (porque ya sucedió lo mismo con anterioridad) y lo suspende de forma preferente en lugar de intentar enviarlo.
No todos los adaptadores tienen un Id. de mensaje único confiable y es menos probable que un almacén transaccional lo tenga. Debido a esto, numerosos adaptadores transaccionales están restringidos al envío de lotes de mensajes únicos.
Procesamiento de otros errores
En el resto de los casos (como en los errores de los mensajes de suspensión), el adaptador debe finalizar la transacción. Cualquier otro resultado produce mensajes duplicados o quita mensajes.
Siempre que el adaptador pueda, debería anular la transacción cuando se produzcan errores en un lote. Sin embargo, hay escenarios en los que el adaptador no puede anular la transacción. En dichos escenarios, se debería suspender el mensaje mediante la misma transacción.
Procesamiento de errores en la recepción transaccional
Un patrón de procesos transaccional común es finalizar una transacción cuando se produce un error. En ese caso todo vuelve al estado anterior y no se pierden datos. Sin embargo, si utiliza datos de un suministro transaccional (por ejemplo, extrayendo filas de una en una de una tabla provisional de una base de datos o extrayendo mensajes de uno en uno de productos de cola como MQSeries o MSMQ), es posible que esto no sea suficiente. Si simplemente finaliza la transacción, vuelve atrás y recoge los mismos datos de nuevo, es posible que se produzca el mismo error y que el sistema se quede bloqueado en un bucle repetido.
El adaptador de SQL en una versión anterior de BizTalk Server se envió con este comportamiento. Sin embargo, poco después de liberar el adaptador, el comportamiento se cambia para intentar suspender un mensaje con errores y confirmar la transacción. Al mover un mensaje a la cola de suspensión en la misma transacción y, a continuación, confirmar la transacción, se evita que se pierdan datos y, además, permite que el adaptador pase datos no válidos.
Cuando la parte de recepción de un adaptador se pasa un mensaje de error en respuesta a una operación Enviar mensaje, el adaptador debe procesar ese error y mover el mensaje a la cola Suspendida.
En el caso de lotes transaccionales en los que el adaptador ha creado el objeto de transacción y envía mensajes en la transacción, el adaptador debería mover el mensaje de forma lógica a la cola de suspensión en la misma transacción cuando se produce el error. La transacción asegura que no se quitan datos aunque provoquen errores.
Controlar mensajes sin suscripciones
BizTalk Server no acepta que se publique un mensaje en su base de datos de cuadro de mensajes si no hay suscripciones definidas que lo acepten. Las orquestaciones o los puertos de envío registran las suscripciones. Se pueden definir numerosas suscripciones, en cuyo caso el mensaje se envía a varios destinos. Si no hay suscripciones, BizTalk Server rechaza el mensaje y no intenta suspenderlo. Si el adaptador no controla este error y suspende el mensaje de forma explícita, se quita el mensaje y es posible que se pierdan sus datos. Es evidente que un adaptador transaccional puede finalizar la transacción y devolver el mensaje a su destino.
Búsqueda con la secuencia de recepción
La secuencia del lado de recepción debe admitir el método Seek para que BizTalk Server pueda suspender el mensaje en un error de canalización. Si la secuencia de mensajes no se puede buscar, BizTalk Server genera un error cuando intenta ejecutar Seek.
En muchos casos, apoyar a Seek no es fácil. Cuando se transmiten datos por secuencias desde una red, por ejemplo, puede resultar difícil volver al recurso de red y solicitar los datos de nuevo.
Varios adaptadores que se incluyen con BizTalk Server ponen en cola los datos de mensaje en un archivo de un disco al mismo tiempo que BizTalk Server lee los datos. Esto permite al adaptador usar Seek en ese archivo si encuentra un error (por ejemplo, en el procesamiento de canalización de los datos del mensaje). Internamente, el adaptador usa la clase ReadOnlySeekableStream que encapsula una secuencia entrante no buscable y se desborda en el disco cuando se alcanza un umbral de tamaño configurable. En caso de que haya mensajes más pequeños que el tamaño del umbral, nunca se utiliza el disco.
Considerar opciones configurables por el usuario para el control de errores
En algunos casos no existe una respuesta correcta para un error. Si esto sucede, debería considerar una opción configurable por el usuario para elegir entre comportamientos. El adaptador de MQSeries realiza esta operación.
El problema con que el adaptador suspenda los mensajes cuando ve un error es que la cola suspendida en BizTalk Server es algo de un "agujero negro". Es relativamente fácil obtener mensajes en la cola, pero es más difícil sacarlos de nuevo.
Es posible que algunos usuarios del adaptador no deseen utilizar la cola de suspensión. Por ejemplo, en el caso del adaptador de MQSeries, el usuario cuenta con una opción de configuración para realizar una de las siguientes operaciones:
Configurar el adaptador para que finalice la transacción actual y se deshabilite cuando vea un error.
Suspender el mensaje con errores y confirmar la transacción. El adaptador realiza esta operación incluso cuando BizTalk Server ha suspendido el mensaje correctamente. Esta acción cumple los requisitos del cliente incluso si provoca que el registro de eventos no sea del todo correcto.
Implementar órdenes de recepción mediante un único subproceso y a la espera de BatchComplete
La interfaz de BizTalk Server está diseñada para conseguir rendimiento y la capacidad para escalar admitiendo concurrencia. Sin embargo, si desea una recepción estrictamente ordenada de mensajes (como la que se requiere en ocasiones cuando se reciben mensajes de un producto de cola de mensajes, como MQSeries o MSMQ), deberá realizar algunas operaciones adicionales en el adaptador para deshabilitar esa concurrencia. Esto se puede llevar a cabo en dos pasos:
Debe utilizar un único subproceso para el procesamiento de todos los datos en el adaptador.
Debe esperar a que BizTalk Server procese por completo cada lote. Este requisito es importante y se puede conseguir utilizando primitivas de sincronización de subprocesos .NET. Por ejemplo, con autoResetEvent, haría lo siguiente:
Declare el objeto de evento al que puede tener acceso tanto el subproceso de trabajo principal como el objeto de devolución de llamada BatchComplete .
En el subproceso de trabajo principal, envíe los mensajes al lote como de costumbre, pero, a continuación, llame a AutoResetEvent.Reset en el objeto de evento justo antes de la llamada al lote IBTTransportBatch::D one.
Llame a AutoResetEvent.WaitOne en el objeto de evento desde este mismo subproceso. Esto provoca el bloqueo del subproceso de trabajo principal. En la devolución de llamada de BatchComplete de BizTalk Server, a continuación, llama a AutoResetEvent.Set en el mismo objeto de evento para desbloquear el subproceso de trabajo para que esté listo para procesar otro mensaje.
Se recomienda encarecidamente que la ordenación de recepción como esta se pueda configurar porque provoca una degradación significativa del rendimiento. Numerosos escenarios de usuarios, si no se trata de la mayoría, no requieren órdenes de mensajes. La suspensión de mensajes puede interrumpir también la orden. Lo que se deba hacer en este caso exactamente depende de la aplicación, por lo tanto lo mejor que puede hacer el adaptador es ofrecer al usuario un punto de configuración.
En escenarios ordenados, algunos clientes han declarado que preferirían detener el procesamiento, es decir, deshabilitar el adaptador en lugar de interrumpir la orden. El adaptador de MQSeries, que admite la recepción ordenada, proporciona esta opción al usuario.
Controlar errores de lote específicos de envíos
Controlar el reintento y el procesamiento por lotes de envíos
A continuación se muestra un ejemplo frecuente de procesamiento por lotes de envíos:
BizTalk Server proporciona un lote de mensajes al adaptador.
Cuando el adaptador determina que ha entregado el mensaje en su destino de forma correcta, ejecuta la eliminación en BizTalk Server para indicar que está listo. (Como es habitual, varios mensajes de eliminación pueden procesarse en lotes de forma arbitraria para mejorar el rendimiento.)
Si el adaptador de envíos produce errores al procesar un mensaje, se puede realizar una de las siguientes operaciones con ese mensaje:
El adaptador debería decir a BizTalk Server que quiere que se reintente un mensaje. BizTalk Server no reintenta de forma automática el mensaje. BizTalk Server mantiene un recuento de los reintentos, que puede consultarse en el contexto del mensaje.
El adaptador puede determinar que no puede procesar un mensaje. En ese caso, el adaptador puede mover el mensaje al siguiente transporte. El adaptador lo hace con la llamada MoveToNextTransport en el objeto Batch .
El adaptador puede mover el mensaje a la cola de suspensión.
El adaptador determina lo que le ocurrirá al mensaje. Sin embargo, se recomienda que cuente con adaptadores que se comporten de forma coherente ya que esto hace que se admita de forma más sencilla la instalación de BizTalk Server.
Se recomienda encarecidamente que los adaptadores se comporten como se describe a continuación. Los adaptadores incluidos con BizTalk Server se comportan de la siguiente forma.
Comportamiento recomendado para el control de errores de envío en un lote
El adaptador de envío recibe algunos mensajes y los envía a BizTalk Server.
Por cada mensaje correcto, el adaptador debería eliminar ese mensaje en BizTalk Server. Toda la comunicación que se devuelve a BizTalk Server se produce mediante lotes; las eliminaciones también se pueden procesar por lotes. No tiene que ser el mismo lote que BizTalk Server creó en el adaptador. Si hay mensajes de respuesta (como en un escenario SolicitResponse), se deberían enviar de vuelta a BizTalk Server (con SubmitResponse) junto con la eliminación asociada.
Si los mensajes no se han procesado de forma correcta en el adaptador, compruebe el número de reintentos.
Si no se ha superado el número de reintentos, reenvíe el mensaje a BizTalk Server, sin olvidarse de definir el tiempo de reintentos en el mensaje. El contexto del mensaje proporciona el número y el intervalo de reintentos que debería utilizar el adaptador.
Si se superó el número de reintentos, el adaptador debe intentar mover el mensaje mediante MoveToNextTransport. Los mensajes reenviar y MoveToNextTransport se pueden mezclar con las eliminaciones del mismo lote en BizTalk Server. Esto no es necesario, pero puede ser un paso útil.
La reenvío y MoveToNextTransport son formas de que el adaptador se ocupe de los errores. Pero, es posible que se produzcan errores dentro del procesamiento del error. En este caso, al procesar la respuesta de BizTalk Server (en el método BatchComplete), el adaptador debe crear otro lote en BizTalk Server para indicar qué hacer con ese error.
Siga los pasos que se presentan a continuación cuando se procese un error que se ha producido en el procesamiento de otro error:
Si se produce un error en la reenvío, use MoveToNextTransport.
Si se produce un error en MoveToNextTransport , use MoveToSuspendQ.
Debe continuar con la creación de lotes en BizTalk Server hasta que reciba una acción correcta en BizTalk Server.
Serialización de propiedad del contexto de mensaje
Todos los objetos que estén asignados a una propiedad de contexto de mensaje deben ser serializables. De lo contrario, el motor de mensajería producirá una excepción de tipo E_NOINTERFACE. Este valor devuelto representa de forma ambigua un objeto no serializable que intenta que se le asigne al contexto del mensaje.