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.
Un mensaje dudoso es un mensaje que ha superado el número máximo de intentos de entrega a la aplicación. Esta situación puede surgir cuando una aplicación basada en cola no puede procesar un mensaje debido a errores. Para satisfacer las demandas de confiabilidad, una aplicación en cola recibe mensajes en una transacción. Anular la transacción en la que un mensaje en cola se recibió deja el mensaje en la cola para que el mensaje se vuelva a intentar con una nueva transacción. Si no se corrige el problema que provocó la anulación de la transacción, la aplicación receptora puede quedar bloqueada en un bucle que recibe y anula el mismo mensaje hasta que se haya superado el número máximo de intentos de entrega y se produzca un mensaje dudoso.
Un mensaje puede convertirse en un mensaje nocivo por muchas razones. Las razones más comunes son específicas de la aplicación. Por ejemplo, si una aplicación lee un mensaje de una cola y realiza algún procesamiento de base de datos, es posible que la aplicación no obtenga un bloqueo en la base de datos, lo que hace que anule la transacción. Dado que se anuló la transacción de base de datos, el mensaje permanece en la cola, lo que hace que la aplicación vuelva a leer el mensaje una segunda vez y realice otro intento de adquirir un bloqueo en la base de datos. Los mensajes también pueden convertirse en veneno si contienen información no válida. Por ejemplo, un pedido de compra puede contener un número de cliente no válido. En estos casos, la aplicación puede anular voluntariamente la transacción y forzar que el mensaje se convierta en un mensaje dudoso.
En raras ocasiones, los mensajes pueden no enviarse a la aplicación. La capa de Windows Communication Foundation (WCF) puede encontrar un problema con el mensaje, como si el mensaje tiene el marco incorrecto, las credenciales de mensaje no válidas asociadas o un encabezado de acción no válido. En estos casos, la aplicación nunca recibe el mensaje; sin embargo, el mensaje todavía puede convertirse en un mensaje dudoso y procesarse manualmente.
Control de mensajes venenosos
En WCF, el control de mensajes dudosos proporciona un mecanismo para que una aplicación receptora trate los mensajes que no se pueden enviar a la aplicación o mensajes que se envían a la aplicación, pero que no se pueden procesar debido a motivos específicos de la aplicación. El control de mensajes dudosos se configura mediante las siguientes propiedades en cada uno de los enlaces en cola disponibles:
ReceiveRetryCount
. Valor entero que indica el número máximo de veces que se reintenta la entrega de un mensaje de la cola de aplicaciones a la aplicación. El valor predeterminado es 5. Esto es suficiente en los casos en los que un reintento inmediato corrige el problema, como con un interbloqueo temporal en una base de datos.MaxRetryCycles
. Valor entero que indica el número máximo de ciclos de reintento. Un ciclo de reintento consiste en transferir un mensaje de la cola de la aplicación a una subcola de intento y, después de un retraso configurable, de la subcola de intento de vuelta a la cola de la aplicación para reintentar la entrega. El valor predeterminado es 2. En Windows Vista, el mensaje se intenta un máximo de (ReceiveRetryCount
+1) * (MaxRetryCycles
+ 1) veces.MaxRetryCycles
se omite en Windows Server 2003 y Windows XP.RetryCycleDelay
. Retraso de tiempo entre ciclos de reintento. El valor predeterminado es de 30 minutos.MaxRetryCycles
yRetryCycleDelay
juntos proporcionan un mecanismo para solucionar el problema en el que un reintento después de un retraso periódico corrige el problema. Por ejemplo, esto maneja un conjunto de filas bloqueado en SQL Server mientras la confirmación de la transacción está pendiente.ReceiveErrorHandling
. Una enumeración que indica la acción a realizar para un mensaje en el que se ha producido un error tras intentar el número máximo de reintentos. Los valores pueden ser Fault, Drop, Reject y Move. La opción de unidad predeterminada es Fault.Culpa. Esta opción envía un error al agente de escucha que provocó el error en
ServiceHost
. Algunos mecanismos externos deben quitar el mensaje de la cola de aplicaciones para que la aplicación pueda seguir procesando mensajes de la cola.Soltar. Esta opción elimina el mensaje venenoso y el mensaje nunca se entrega a la aplicación. Si la propiedad
TimeToLive
del mensaje ha expirado a este punto, el mensaje puede aparecer en la cola de mensajes no entregados del remitente. Si no es así, el mensaje no aparece en ningún lugar. Esta opción indica que el usuario no ha especificado qué hacer si se pierde el mensaje.Rechazar. Esta opción solo está disponible en Windows Vista. Esto indica a Message Queuing (MSMQ) que devuelva una confirmación negativa al administrador de colas de envío que la aplicación no pueda recibir el mensaje. El mensaje se coloca en la cola de mensajes no enviados del administrador de la cola emisora.
Mover. Esta opción solo está disponible en Windows Vista. Esto mueve el mensaje dudoso a una cola de mensajes dudosos para su posterior procesamiento mediante una aplicación de control de mensajes dudosos. La cola de mensajes dudosos es una subcola de la cola de la aplicación. Una aplicación de control de mensajes dudosos puede ser un servicio WCF que lee los mensajes fuera de la cola de dudosa. La cola dudosa es una subcola de la cola de la aplicación y se puede direccionar como net.msmq://<machine-name>/applicationQueue;poison, donde machine-name es el nombre del equipo en el que reside la cola y applicationQueue es el nombre de la cola específica de la aplicación.
A continuación se muestra el número máximo de intentos de entrega realizados para un mensaje:
((ReceiveRetryCount+1) * (MaxRetryCycles + 1)) en Windows Vista.
(ReceiveRetryCount + 1) en Windows Server 2003 y Windows XP.
Nota:
No se reintenta la entrega de un mensaje una vez que se ha realizado correctamente.
Para realizar un seguimiento del número de veces que se intenta leer un mensaje, Windows Vista mantiene una propiedad de mensaje duradera que cuenta el número de anulaciones, así como una propiedad de recuento de movimiento que cuenta el número de veces que el mensaje se mueve entre la cola de la aplicación y las subcolas. El canal WCF lo utiliza con frecuencia para calcular los reintentos de recepción y el recuento de ciclos de reintento. En Windows Server 2003 y Windows XP, el canal WCF mantiene en memoria el contador de abortos, y se restablece si la aplicación falla. Además, el canal WCF puede contener los recuentos de anulaciones de hasta 256 mensajes en la memoria en cualquier momento. Si se lee el mensaje número 257, se restablece el recuento de la anulación del mensaje más antiguo.
Las propiedades de recuento de la anulación y recuento de movimiento están disponibles para la operación del servicio a través del contexto de la operación. En el ejemplo de código siguiente se muestra cómo acceder a ellos.
MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine($"Abort count: {mqProp.AbortCount} ");
Console.WriteLine($"Move count: {mqProp.MoveCount} ");
// code to submit purchase order ...
WCF proporciona dos enlaces en cola estándar:
NetMsmqBinding. Un enlace de .NET Framework adecuado para realizar comunicaciones basadas en cola con otros puntos de conexión WCF.
MsmqIntegrationBinding. Un enlace conveniente para comunicar con aplicaciones Message Queuing existentes.
Nota:
Puede modificar las propiedades de estos enlaces en función de los requisitos del servicio WCF. Todo el mecanismo de control de mensajes dudosos es local a la aplicación receptora. El proceso es invisible para la aplicación de envío a menos que la aplicación receptora se detenga y envíe una confirmación negativa al remitente. En ese caso, el mensaje se mueve a la cola de mensajes no enviados del remitente.
Procedimiento recomendado: Controlar MsmqPoisonMessageException
Cuando el servicio determina que un mensaje es dudoso, el transporte en cola arroja MsmqPoisonMessageException que contiene LookupId
del mensaje dudoso.
Una aplicación receptora puede implementar la IErrorHandler interfaz para controlar los errores que la aplicación requiere. Para obtener más información, vea Extender el control sobre el control de errores y los informes.
La aplicación puede requerir algún tipo de control automatizado de mensajes dudosos que mueva los mensajes dudosos a una cola de mensajes dudosos para que el servicio pueda acceder al resto de los mensajes de la cola. El único escenario para utilizar el mecanismo del controlador de errores para realizar escuchas para las excepciones de mensajes dudosos es cuando ReceiveErrorHandling está establecido en Fault. El ejemplo de mensaje envenenado para Message Queuing 3.0 muestra este comportamiento. A continuación se describen los pasos que se deben seguir para controlar los mensajes dudosos, incluidos los procedimientos recomendados:
Asegúrese de que la configuración de veneno refleje los requisitos de la aplicación. Al trabajar con la configuración, asegúrese de que comprende las diferencias entre las funcionalidades de Message Queuing en Windows Vista, Windows Server 2003 y Windows XP.
En caso de que sea necesario, implemente
IErrorHandler
para controlar los errores de los mensajes dudosos. Dado que establecerReceiveErrorHandling
aFault
requiere un mecanismo manual para mover el mensaje dañino fuera de la cola o para corregir un problema externo dependiente, el uso típico es implementarIErrorHandler
cuandoReceiveErrorHandling
se establece enFault
, como se muestra en el código siguiente.class PoisonErrorHandler : IErrorHandler { public void ProvideFault(Exception error, MessageVersion version, ref Message fault) { // No-op -We are not interested in this. This is only useful if you want to send back a fault on the wire…not applicable for queues [one-way]. } public bool HandleError(Exception error) { if (error != null && error.GetType() == typeof(MsmqPoisonMessageException)) { Console.WriteLine($" Poisoned message -message look up id = {((MsmqPoisonMessageException)error).MessageLookupId}"); return true; } return false; } }
Cree un
PoisonBehaviorAttribute
que pueda usar el comportamiento del servicio. El comportamiento instalaIErrorHandler
en el distribuidor. Observe el siguiente ejemplo de código.public class PoisonErrorBehaviorAttribute : Attribute, IServiceBehavior { Type errorHandlerType; public PoisonErrorBehaviorAttribute(Type errorHandlerType) { this.errorHandlerType = errorHandlerType; } void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase) { } void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters) { } void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase) { IErrorHandler errorHandler; try { errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType); } catch (MissingMethodException e) { throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must have a public empty constructor", e); } catch (InvalidCastException e) { throw new ArgumentException("The errorHandlerType specified in the PoisonErrorBehaviorAttribute constructor must implement System.ServiceModel.Dispatcher.IErrorHandler", e); } foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher; channelDispatcher.ErrorHandlers.Add(errorHandler); } } }
Asegúrese de que su servicio se anote con el atributo de comportamiento de mensajes venenosos.
Además, si ReceiveErrorHandling
se establece en Fault
, ServiceHost
genera un error al encontrar el mensaje dudoso. Puede enlazar con el evento defectuoso y apagar el servicio, realizar acciones correctivas y reiniciar. Por ejemplo, puede tomar nota del LookupId
de la MsmqPoisonMessageException propagada a IErrorHandler
y, cuando el host de servicio genere el error, puede utilizar la API System.Messaging
para recibir el mensaje de la cola, utilizando el LookupId
para quitarlo de la cola y almacenarlo en algún almacén externo u otra cola. A continuación, puede reiniciar ServiceHost
para reanudar el procesamiento normal. El control de mensajes dudosos en MSMQ 4.0 muestra este comportamiento.
Transacción Time-Out y Mensajes Envenenados
Se puede producir una clase de errores entre el canal de transporte en cola y el código de usuario. Estos errores se pueden detectar mediante capas entre ellas, como la capa de seguridad del mensaje o la lógica de distribución del servicio. Por ejemplo, cuando se detecta la ausencia de un certificado X.509 en el nivel de seguridad SOAP y la ausencia de una acción son casos en los que el mensaje no se distribuye a la aplicación. Cuando esto sucede, el modelo del servicio descarta el mensaje. Dado que el mensaje se lee en una transacción y no se puede proporcionar un resultado para esa transacción, eventualmente la transacción agota el tiempo de espera, se aborta y el mensaje se vuelve a colocar en la cola. En otras palabras, para una determinada clase de errores, la transacción no se anula inmediatamente, sino que espera hasta que expire el tiempo de espera de la transacción. Puede modificar el tiempo de espera de la transacción para un servicio mediante ServiceBehaviorAttribute.
Para cambiar el tiempo de espera de la transacción en todo el equipo, modifique el archivo machine.config y establezca el tiempo de espera de la transacción adecuado. Es importante tener en cuenta que, en función del tiempo de espera que se establezca en la transacción, la transacción finalmente se anulará y volverá a la cola y su cuenta de anulación se incrementará. Finalmente, el mensaje se convierte en dudoso y se elimina de la forma que especifique la configuración del usuario.
Sesiones y mensajes dudosos
Una sesión sufre los mismos procedimientos de reintento y control de mensajes dudosos como un mensaje único. Las propiedades enumeradas anteriormente para los mensajes dudosos se aplican a toda la sesión. Esto significa que se reintenta la sesión completa y se envía a una cola de mensajes dudosos final o a la cola de mensajes no enviados del remitente si se rechaza el mensaje.
Procesamiento por lotes y mensajes dudosos
Si un mensaje se convierte en un mensaje envenenado y forma parte de un lote, todo el lote se revierte y el canal vuelve a leer un mensaje a la vez. Para obtener más información sobre el procesamiento por lotes, consulte Procesamiento por lotes de mensajes en una transacción.
Control de mensajes dudosos para mensajes en una cola de mensajes dudosos
El manejo de mensajes dañinos no finaliza cuando un mensaje se coloca en la cola de mensajes dañinos. Los mensajes de la cola de mensajes dudosos también se deben leer y controlar. Puede utilizar un subconjunto de los valores de control de mensajes dudosos al leer mensajes de la subcola final de mensajes dudosos. La configuración aplicable es ReceiveRetryCount
y ReceiveErrorHandling
. Puede establecer ReceiveErrorHandling
en Drop, Reject o Fault.
MaxRetryCycles
se omite y se produce una excepción si ReceiveErrorHandling
se establece en Mover.
Diferencias de Windows Vista, Windows Server 2003 y Windows XP
Como se indicó anteriormente, no todas las opciones de control de mensajes dudosos se aplican a Windows Server 2003 y Windows XP. Las siguientes diferencias clave entre Message Queuing en Windows Server 2003, Windows XP y Windows Vista son relevantes para el control de mensajes dudosos:
Message Queuing en Windows Vista admite subconsultas, mientras que Windows Server 2003 y Windows XP no admiten subconsultas. Las subcolas se utilizan en el control de mensajes dudosos. Las colas de reintento y la cola dudosa son subcolas en la cola de la aplicación que se crea dependiendo de los valores de control del mensaje dudoso.
MaxRetryCycles
dicta cuántas subcolas de reintento se crean. Por lo tanto, cuando se ejecuta en Windows Server 2003 o Windows XP,MaxRetryCycles
se omiten yReceiveErrorHandling.Move
no se permiten.Message Queue Server en Windows Vista admite la confirmación negativa, mientras que Windows Server 2003 y Windows XP no. Una confirmación de que no se pudo realizar la acción del administrador de la cola receptora hace que el administrador de la cola emisora coloque el mensaje rechazado en la cola de mensajes no enviados. Por lo tanto,
ReceiveErrorHandling.Reject
no se permite con Windows Server 2003 y Windows XP.Message Queuing en Windows Vista admite una propiedad de mensaje que mantiene el recuento del número de veces que se intenta la entrega de mensajes. Esta propiedad de recuento de anulaciones no está disponible en Windows Server 2003 ni Windows XP. WCF mantiene el recuento de anulaciones en la memoria, por lo que es posible que esta propiedad no contenga un valor preciso cuando más de un servicio WCF lee el mismo mensaje en una granja de servidores.