2012-04-28 20 views
10

¿Cuál es una buena manera de que un actor intente algo nuevamente cuando falla, pero con intervalos de tiempo crecientes entre los intentos? Digamos que quiero que el actor intente de nuevo después de 15 segundos, luego de 30 segundos, luego de cada minuto durante un número limitado de veces.Akka: ¿Cómo programar reintentos en fallas con intervalos de retardo crecientes?

Aquí es lo que he llegado con:

  • el método del actor que realiza el trabajo real tiene un parámetro opcional RetryInfo que, si está presente, contiene el número de la reintento actualmente estamos en
  • en caso de fallo, el actor enviará sí mismo un nuevo ScheduleRetryMessage con retryCount + 1, a continuación, lanzar una RuntimeException
  • otro actor supervisa el actor trabajador, utilizando new OneForOneStrategy(-1, Duration.Inf() regresar Resume como su directiva. El actor tiene ningún estado, por lo Resume debería estar bien
  • al recibir el ScheduleRetryMessage, el actor se
    • si retryCount < MAX_RETRIES: utilizar el planificador de Akka para programar el envío de un RetryMessage después de que el retardo deseado
    • otra cosa: por fin se dio por vencido, el envío de un mensaje a otro actor para el informe de errores

¿es esta una buena solución o hay un mejor enfoque?

Respuesta

8

Puede tener un supervisor que comience con el actor trabajador. La sugerencia de los documentos es declarar un enrutador de tamaño uno para el trabajador. El supervisor mantendría un registro del número de reintentos, luego programará el envío del mensaje al trabajador según corresponda.

Aunque crearía otra capa de actores, esto me parece más limpio ya que mantendría la funcionalidad de supervisión fuera del trabajador. Idealmente, podría hacer que este 1 supervisor sea n trabajador, pero creo que debería usar Lifecycle Monitoring para obtener un error de un actor secundario. En ese caso, puede mantener un mapa de [ActorRef, Int] para realizar un seguimiento del número de intentos de todos los trabajadores supervisados. La política de supervisión se reanudaría, pero si alcanzó los reintentos máximos, podría enviar un PoisonPill al ActorRef infractor.

+0

Idea interesante, intentaré eso. ¡Gracias! –

7

En tales casos utilizo la supervisión estándar. Un padre/actor supervisor define los reintentos dentro de una ventana de tiempo. El niño trabajador de reintentar simplemente vuelve a programar el mensaje que provocó la falla con un retraso en preRestart().

Si el niño reintegrado es bastante complejo, puede considerar interconectar un actor intermedio. Ese actor simplemente aumenta la supervisión. En preRestart, el actor intermedio programa un mensaje de reinicio (demorado). Como el actor intermedio conserva su estado, simplemente puede reiniciar el actor trabajador (con retraso).

Como puede ver, la parte que se retrasa puede estar en preRestart o al inicio del trabajador.