microsoft management azure azureservicebus

management - panel azure login



¿Se puede demorar el bus de servicio Azure antes de volver a intentar enviar un mensaje? (2)

Tenga cuidado aquí porque creo que está confundiendo la función de reintento con el mecanismo automático de Complete / Abandon para el manejo de mensajes basado en eventos de OnMessage . El mecanismo de reintento incorporado entra en juego cuando falla una llamada al Bus de servicio. Por ejemplo, si llama para establecer un mensaje como completo y falla, entonces el mecanismo de reintento se activaría. Si está procesando un mensaje, se produce una excepción en su propio código que NO provocará un reintento a través de la función de reintento. Su pregunta no es explícita sobre si el error proviene de su código o si intenta comunicarse con el bus de servicio.

Si de hecho está después de modificar la política de reintento que ocurre cuando se produce un error al intentar comunicarse con el bus de servicio, puede modificar la RetryPolicy que está configurada en el MessageReciver . Hay un RetryExponitial que se usa de manera predeterminada, así como también un RetryPolicy abstracto del que puede crear el suyo.

Lo que creo que busca es más control sobre lo que sucede cuando se obtiene una excepción al procesar, y se desea seguir trabajando en ese mensaje. Hay algunas opciones:

Cuando crea su manejador de mensajes, puede configurar OnMessageOptions . Una de las propiedades es "Autocompletar". De forma predeterminada, esto se establece en verdadero, lo que significa que tan pronto como se complete el procesamiento del mensaje, el método Complete se llama automáticamente. Si ocurre una excepción, se llama automáticamente a abandono, que es lo que está viendo. Al establecer Autocompletar en falso, debe llamar a Completo por su cuenta desde el controlador de mensajes. Si no lo hace, el bloqueo del mensaje finalmente se agotará, que es uno de los comportamientos que está buscando.

Por lo tanto, podría escribir su controlador para que, si ocurre una excepción durante su procesamiento, simplemente no llame a Complete . El mensaje permanecería en la cola hasta que se acabe el bloqueo y luego vuelva a estar disponible. Se aplica el mecanismo estándar de letras muertas y después de x intentos se colocará automáticamente en la cola del deadletter.

Una precaución de manejo de esta manera es que cualquier tipo de excepción se tratará de esta manera. Realmente necesita pensar qué tipos de excepciones están haciendo esto y si realmente desea impulsar el procesamiento o no. Por ejemplo, si está llamando a un sistema de terceros durante su procesamiento y le da una excepción que sabe que es transitoria, excelente. Sin embargo, si te da un error que sabes que será un gran problema, entonces puedes decidir hacer algo más en el sistema además de simplemente rescatar el mensaje.

También puede consultar el método " Defer ". De hecho, este método no permitirá que ese mensaje se procese fuera de la cola, a menos que se extraiga específicamente por su número de secuencia. Tu código debería recordar el valor del número de secuencia y tirar de él. Aunque esto no es exactamente lo que describes.

Otra opción es que puede alejarse del estilo OnMessage, procesado por eventos, de procesar mensajes. Si bien esto es muy útil, no tienes mucho control sobre las cosas. En su lugar, conecte su propio ciclo de procesamiento y maneje el abandono / complete por su cuenta. También tendrá que ocuparse de la administración de llamadas concurrentes o de subprocesamiento que le brinda el patrón OnMessage. Esto puede ser más trabajo, pero tiene lo último en flexibilidad.

Finalmente, creo que el motivo por el cual la llamada que realizó a AbandonAsync pasar las propiedades que deseaba modificar no funcionó es porque esas propiedades hacen referencia a las propiedades de metadatos en el método, no a las propiedades estándar en BrokeredMessage.

Azure Service Bus admite un mecanismo de reintento integrado que hace que un mensaje abandonado sea inmediatamente visible para otro intento de lectura. Intento usar este mecanismo para manejar algunos errores transitorios, pero el mensaje está disponible inmediatamente después de ser abandonado.

Lo que me gustaría hacer es hacer que el mensaje sea invisible durante un período de tiempo después de que se abandone, preferiblemente de acuerdo con una política de incremento exponencial.

Intenté establecer la propiedad ScheduledEnqueueTimeUtc al abandonar el mensaje, pero parece que no tiene ningún efecto:

var messagingFactory = MessagingFactory.CreateFromConnectionString(...); var receiver = messagingFactory.CreateMessageReceiver("test-queue"); receiver.OnMessageAsync(async brokeredMessage => { await brokeredMessage.AbandonAsync( new Dictionary<string, object> { { "ScheduledEnqueueTimeUtc", DateTime.UtcNow.AddSeconds(30) } }); } });

Consideré no abandonar el mensaje y dejar que el bloqueo caduque, pero esto requeriría tener alguna forma de influir en cómo MessageReceiver especifica la duración del bloqueo en un mensaje, y no puedo encontrar nada en la API que me permita cambia este valor Además, no sería posible leer el conteo de entrega del mensaje (y, por lo tanto, tomar una decisión sobre cuánto tiempo esperar al próximo intento) hasta que ya se requiera el bloqueo.

¿Se puede influir de algún modo en la política de reintento en el Bus de mensajes o puede introducirse artificialmente una demora de alguna otra manera?


De hecho, hice la misma pregunta el año pasado (la implementación a un lado) con los tres enfoques que podría pensar en mirar la API. @ClemensVasters, que trabaja en el equipo SB, respondió que usar Defer con algún tipo de re-recepción es realmente la única manera de controlar esto con precisión.

Puede leer mi comentario en su respuesta para obtener un enfoque específico para hacerlo, donde sugiero utilizar una cola secundaria para almacenar mensajes que indiquen qué mensajes principales se han aplazado y deben volver a recibirse de la cola principal. Luego puede controlar cuánto tiempo espera al configurar ScheduledEnqueueTimeUtc en esos mensajes secundarios para controlar exactamente cuánto tiempo espera antes de volver a intentarlo.