Control de mensajes dudosos
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 se puede presentar cuando una aplicación basada en cola no puede procesar un mensaje debido a los errores. Para satisfacer la confiabilidad que exige, una aplicación en cola recibe los mensajes bajo 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 produjo la anulación de la transacción, la aplicación receptora se puede atascar en una recepción de bucle y anulando el mismo mensaje hasta que supere el número máximo de intentos de entrega, y se produzca un mensaje dudoso.
Un mensaje se puede volver un mensaje dudoso 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 pueda obtener un bloqueo en la base de datos, haciendo que se anule la transacción. Dado que la transacción de base de datos se anula, 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 se pueden volver dudosos si contienen la información no válida. Por ejemplo, un pedido de compra puede contener un número del cliente no válido. En estos casos, la aplicación puede anular voluntariamente la transacción y forzar al mensaje a convertirse en un mensaje dudoso.
En raras ocasiones, se puede producir un error en la distribución a la aplicación. En el nivel de Windows Communication Foundation (WCF) se pueden producir problemas con el mensaje; por ejemplo, si el mensaje tiene el marco incorrecto, si tiene adjuntas credenciales de mensaje no válidas o si hay un encabezado de acción no válido. En estos casos, la aplicación nunca recibe el mensaje; sin embargo, el mensaje todavía se puede convertir en un mensaje dudoso y procesar manualmente.
Control de mensajes dudosos
En WCF, el control de mensajes dudosos proporciona un mecanismo para que una aplicación receptora trate con mensajes que no se pueden distribuir a la aplicación o mensajes que se distribuyen a la aplicación pero que en los que se produce un error al procesarlos debido a razones específicas 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. Un valor entero que indica el número máximo de horas para reintentar la entrega de un mensaje de la cola de la aplicación a la aplicación. El valor predeterminado es 5. Esto es suficiente en casos donde un reintento inmediato corrige el problema, como ocurre con un interbloqueo temporal en una base de datos.
MaxRetryCycles. Un 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 prueba un máximo de (ReceiveRetryCount +1) * (MaxRetryCycles + 1) veces. MaxRetryCycles se omite en Windows Server 2003 y Windows XP.
RetryCycleDelay. El tiempo de retardo entre los ciclos de reintento. El valor predeterminado es 30 minutos. MaxRetryCycles y RetryCycleDelay proporcionan juntos un mecanismo para resolver el problema donde un reintento después de un retraso periódico corrige el problema. Por ejemplo, esto controla un conjunto de filas bloqueado en confirmación de la transacción pendiente de SQL Server.
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.
Fault. Esta opción envía un error al agente de escucha que provocó el error en ServiceHost. El mensaje debe ser eliminado de la cola de la aplicación por algún mecanismo externo antes de que la aplicación pueda continuar procesando los mensajes de la cola.
Drop. Esta opción quita el mensaje dudoso y el mensaje nunca llega a la aplicación. Si la propiedad TimeToLive del mensaje ha expirado en este punto, el mensaje puede aparecer en la cola de mensajes no enviados del remitente. Si no, el mensaje no aparece en ningún sitio. Esta opción indica que el usuario no ha especificado qué hacer si se pierde el mensaje.
Reject. Esta opción solo está disponible en Windows Vista. Indica a Message Queue Server (MSMQ) que devuelva una confirmación negativa al administrador de la cola emisora para indicar que la aplicación no puede recibir el mensaje. El mensaje se coloca en la cola de mensajes no enviados del administrador de la cola emisora.
Move. Esta opción solo está disponible en Windows Vista. Mueve el mensaje dudoso a una cola de mensajes dudosos para ser procesado posteriormente por 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 expulsa los mensajes de la cola de mensajes dudosos. La cola de mensajes dudosos 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 ordenador que alberta 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 realiza ningún reintento para un mensaje que se entrega correctamente. |
Para realizar un seguimiento del número de veces que se intenta leer un mensaje, Windows Vista mantiene una propiedad de mensaje duradero que cuenta el número de anulaciones y 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 los ciclos de reintento. En Windows Server 2003 y Windows XP, el recuento de la anulación es mantenido en memoria por el canal WCF y se restablece si se produce un error en la aplicación. Así, el canal WCF puede contener los recuentos de la anulación para hasta 256 mensajes en 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 obtener acceso.
MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;
Console.WriteLine("Abort count: {0} ", mqProp.AbortCount);
Console.WriteLine("Move count: {0} ", mqProp.MoveCount);
// code to submit purchase order ...
WCF proporciona dos enlaces en cola estándares:
NetMsmqBinding. Un enlace .NET Framework conveniente para realizar la comunicación basada en cola con otros extremos WCF.
MsmqIntegrationBinding. Un enlace conveniente para comunicar con aplicaciones Message Queue Server existentes.
Nota: |
---|
Puede modificar las propiedades en estos enlaces basándose en los requisitos de su 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 emisora a menos que la aplicación receptora se detenga finalmente y devuelva 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 interfaz IErrorHandler para controlar cualquier error que la aplicación requiera. Para obtener más información, vea Extensión de control a control de errores y creación de informes.
La aplicación puede requerir algún tipo de control automatizado de mensajes dudosos que los aparte a una cola específica de manera que el servicio pueda tener acceso 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 dudoso para Message Queue Server 3.0 demuestra este comportamiento. A continuación se dibujan los pasos a realizar para controlar los mensajes dudosos, incluyendo los procedimientos recomendados:
Asegúrese de que la configuración de mensajes dudosos refleja los requisitos de la aplicación. Al trabajar con los valores, asegúrese de que entienda las diferencias entre las funciones de Message Queue Server en Windows Vista, Windows Server 2003y Windows XP.
Si se requiere, implemente IErrorHandler para controlar los errores de los mensajes dudosos. Dado que al establecer ReceiveErrorHandling en Fault se requiere un mecanismo manual para quitar el mensaje dudoso de la cola o corregir un problema derivado externo, lo normal es implementar IErrorHandler cuando ReceiveErrorHandling se establece en Fault, 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 wirenot 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 = {0}", ((MsmqPoisonMessageException)error).MessageLookupId); return true; } return false; } }
Cree un PoisonBehaviorAttribute que pueda usar el comportamiento del servicio. El comportamiento instala IErrorHandler en el distribuidor. Vea el ejemplo de código siguiente.
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.
<configuration> <appSettings> <!-- use appSetting to configure MSMQ queue name --> <add key="queueName" value=".\private$\ServiceModelSamplesPoison" /> <add key="baseAddress" value="https://localhost:8000/orderProcessor/poisonSample"/> </appSettings> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderProcessorService"> <!-- Define NetMsmqEndpoint --> <endpoint address="net.msmq://localhost/private/ServiceModelSamplesPoison" binding="netMsmqBinding" bindingConfiguration="PoisonBinding" contract="Microsoft.ServiceModel.Samples.IOrderProcessor" /> </service> </services> <bindings> <netMsmqBinding> <binding name="PoisonBinding" receiveRetryCount="0" maxRetryCycles="1" retryCycleDelay="00:00:05" receiveErrorHandling="Fault" /> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>
Además, si ReceiveErrorHandling se establece en Fault, ServiceHost genera un error al encontrar el mensaje dudoso. Puede enlazarlo con el evento que ha generado el error y cerrar el servicio, tomar medidas correctivas y reiniciarlo. 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. Puede reiniciar a continuación ServiceHost para reanudar el procesamiento normal. En Poison Message Handling in MSMQ 3.0 se muestra este comportamiento.
Tiempo de espera de la transacción y mensajes dudosos
Una clase de errores se puede producir entre el canal de transporte en cola y el código de usuario. Estos errores pueden ser detectados por niveles intermedios, como el nivel de seguridad de mensajes o el servicio que distribuye la lógica. 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 de servicio quita el mensaje. Puesto que el mensaje se lee en una transacción y no se puede proporcionar un resultado para la misma, la transacción agota el tiempo de espera, se anula y el mensaje se pone de nuevo en la cola. En otras palabras, para una cierta clase de errores, la transacción no anula inmediatamente sino que espera hasta que se agote el tiempo de espera. Puede modificar el tiempo de espera de la transacción para un servicio utilizando ServiceBehaviorAttribute.
Para cambiar el tiempo de espera de la transacción para todos los equipos, modifique el archivo machine.config y establezca el tiempo de espera adecuado de la transacción. Es importante tener en cuenta que, dependiendo del tiempo de espera establecido en la transacción, la transacción finalmente se anula y regresa a la cola, incrementándose su número de anulación. 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 vuelve un mensaje dudoso y es parte de un lote, se deshace el lote completo y el canal vuelve a leer un mensaje cada vez. Para el procesamiento por lotes Para obtener más información sobre , vea Mensajes por lotes en una transacción
Control de mensajes dudosos para mensajes en una cola de mensajes dudosos
El control de mensajes dudosos no finaliza cuando un mensaje se coloca en la cola de mensajes dudosos. 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. Se omite MaxRetryCycles y se produce una excepción si ReceiveErrorHandling se establece en Move.
Diferencias entre Windows Vista, Windows Server 2003, y Windows XP
Como se ha apuntado anteriormente, no todos los valores de control de mensajes dudosos son aplicables a Windows Server 2003 y Windows XP. Las siguientes diferencias clave entre Message Queue Server (MSMQ) en Windows Vista, Windows Server 2003 y Windows XP son pertinentes para el control de mensajes dudosos:
Message Queue Server en Windows Vista admite subcolas, mientras que Windows Server 2003 y Windows XP no admiten subcolas. 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 ejecutan en Windows Server 2003 o Windows XP, MaxRetryCycles se omiten y no se permite ReceiveErrorHandling.Move.
Message Queue Server en Windows Vista admite confirmación negativa, mientras que Windows Server 2003 y Windows XP no. Una confirmación negativa 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. Como tal, ReceiveErrorHandling.Reject no se permite con Windows Server 2003 y Windows XP.
Message Queue Server en Windows Vista admite una propiedad de mensaje que mantiene un recuento del número de veces que se intenta la entrega del mensaje. Esta propiedad de recuento de anulación no está disponible en Windows Server 2003 y Windows XP. WCF mantiene el recuento de anulación en memoria, por lo que es posible que esta propiedad no contenga un valor preciso cuando el mismo mensaje es leído por más de un servicio WCF en una granja de servidores.
Vea también
Conceptos
Información general de colas
Diferencias en las características de cola en Windows Vista, Windows Server 2003 y Windows XP
Especificación y administración de errores en contratos y servicios