Configuración del comportamiento de reintento en AWS SDK for Java 2.x
Las llamadas a Servicios de AWS pueden fallar ocasionalmente por motivos inesperados. Pueden producirse algunos errores, como la limitación (se supera la frecuencia) o los errores transitorios, si se vuelve a intentar la llamada. AWS SDK for Java 2.x cuenta con un mecanismo integrado para detectar estos errores y reintentar automáticamente la llamada que está habilitado de forma predeterminada para todos los clientes.
En esta página se describe cómo funciona, cómo configurar los distintos modos y personalizar el comportamiento de reintento.
Estrategias de reintento
Una estrategia de reintento es un mecanismo que se utiliza en el SDK para implementar reintentos. Cada cliente del SDK tiene una estrategia de reintento creada en el momento de compilación que no se puede modificar una vez creado el cliente.
La estrategia de reintento tiene las siguientes responsabilidades.
-
Clasificar excepciones como reintentables o no.
-
Calcular el retraso recomendado para esperar antes del siguiente intento.
-
Mantener un bucket de tokens
que proporcione un mecanismo para detener los reintentos cuando fallen un gran porcentaje de las solicitudes y los reintentos no tengan éxito.
nota
Antes del lanzamiento de las estrategias de reintento con la versión 2.26.0 del SDK, las políticas de reintento proporcionaban el mecanismo de reintento en el SDK. La API de política de reintento se compone de la clase RetryPolicysoftware.amazon.awssdk.core.retry, mientras que el paquete software.amazon.awssdk.retries contiene los elementos de la API de estrategia de reintento.
La API de estrategia de reintento se ha introducido como parte de un esfuerzo en todo AWS por unificar las interfaces y el comportamiento de los componentes principales de los SDK.
El SDK para Java 2.x tiene tres estrategias de reintento integradas: estándar, heredada y adaptativa. Las tres estrategias de reintento están preconfiguradas para reintentar en un conjunto de excepciones reintentables. Algunos ejemplos de errores reintentables son los tiempos de espera de socket, la limitación de servicio, los errores de bloqueo positivo o simultáneo y los errores de servicio transitorios.
Estrategia de reintento estándar
La estrategia de reintento estándarRetryStrategy recomendada para casos de uso normales. A diferencia de AdaptiveRetryStrategy, la estrategia estándar suele ser útil en todos los casos de uso de reintento.
La estrategia de reintento estándar lleva a cabo lo siguiente de forma predeterminada.
-
Reintenta en las condiciones configuradas en tiempo de compilación. Puede ajustarla con
StandardRetryStrategy.Builder.#retryOnException -
Reintenta 2 veces con un total de 3 intentos. Puede ajustarla con
StandardRetryStrategy.Builder#maxAttempts(int). -
En el caso de excepciones sin limitación, utiliza la estrategia de retroceso de
BackoffStrategy, con un retraso base de 100 milisegundos y un retraso máximo de 20 segundos. Puede ajustarla con#exponentialDelay StandardRetryStrategy.Builder#backoffStrategy. -
En el caso de excepciones con limitación, utiliza la estrategia de retroceso de
BackoffStrategy#exponentialDelay, con un retraso base de 1 segundo y un retraso máximo de 20 segundos. Puede ajustarla conStandardRetryStrategy.Builder#throttlingBackoffStrategy. -
Realiza interrupción del circuito (deshabilita los reintentos) en caso de que se produzcan muchos errores posteriores. El primer intento siempre se ejecuta, solo se deshabilitan los reintentos. Ajústela con
StandardRetryStrategy.Builder#circuitBreakerEnabled.
Estrategia de reintento heredada
La estrategia de reintento heredadaRetryStrategy para casos de uso normales, sin embargo, ha quedado obsoleta en favor de StandardRetryStrategy. Esta es la estrategia de reintento predeterminada que utilizan los clientes cuando no se especifica otra estrategia.
Se caracteriza por tratar las excepciones con y sin limitación de manera diferente: en el caso de las excepciones con limitación, el retardo base del retroceso es mayor (500 ms) que el retraso base para excepciones sin limitación (100 ms), y las excepciones con limitación no afectan al estado del bucket de tokens.
La experiencia en el uso de esta estrategia a gran escala en AWS ha demostrado que no es particularmente mejor que la estrategia de reintento estándar. Además, no protege los servicios posteriores de las tormentas de reintentos y puede provocar falta de recursos en el cliente.
La estrategia de reintento heredada lleva a cabo lo siguiente de forma predeterminada.
-
Reintenta en las condiciones configuradas en tiempo de compilación. Puede ajustarla con
LegacyRetryStrategy.Builder.#retryOnException -
Reintenta 3 veces con un total de 4 intentos. Puede ajustarla con
LegacyRetryStrategy.Builder#maxAttempts(int). -
En el caso de excepciones sin limitación, utiliza la estrategia de retroceso de
BackoffStrategy#exponentialDelay, con un retraso base de 100 milisegundos y un retraso máximo de 20 segundos. Puede ajustarla conLegacyRetryStrategy.Builder#backoffStrategy. -
En el caso de excepciones con limitación, utiliza la estrategia de retroceso de
BackoffStrategy#exponentialDelay, con un retraso base de 500 milisegundos y un retraso máximo de 20 segundos. Puede ajustarla conLegacyRetryStrategy.Builder#throttlingBackoffStrategy. -
Realiza interrupción del circuito (deshabilita los reintentos) en caso de que se produzcan muchos errores posteriores. La interrupción del circuito nunca evita un primer intento correcto. Puede ajustar este comportamiento con
LegacyRetryStrategy.Builder#circuitBreakerEnabled. -
El estado del interruptor del circuito no se ve afectado por las excepciones de limitación.
Estrategia de reintento adaptativa
La estrategia de reintento adaptativaRetryStrategy para casos de uso con un alto nivel de limitación de recursos.
La estrategia de reintento adaptativa incluye todas las características de la estrategia estándar y agrega un limitador de velocidad en el cliente que mide la tasa de solicitudes con limitación en comparación con las solicitudes sin limitación. La estrategia utiliza esta medida para ralentizar las solicitudes e intentar mantenerlas dentro de un ancho de banda seguro, sin que se produzcan errores de limitación en un caso ideal.
La estrategia de reintento adaptativa lleva a cabo lo siguiente de forma predeterminada.
-
Reintenta en las condiciones configuradas en tiempo de compilación. Puede ajustarla con
AdaptiveRetryStrategy.Builder.#retryOnException -
Reintenta 2 veces con un total de 3 intentos. Puede ajustarla con
AdaptiveRetryStrategy.Builder#maxAttempts(int). -
Utiliza un retardo de retroceso dinámico que se basa en la carga actual frente el recurso posterior.
-
Realiza interrupción del circuito (deshabilita los reintentos) cuando se produce un gran número de errores posteriores. La interrupción del circuito puede impedir un segundo intento en situaciones de suspensión para proteger el servicio posterior.
aviso
La estrategia de reintento adaptativa implica que el cliente trabaja con un único recurso (por ejemplo, una tabla de DynamoDB o un bucket de Amazon S3).
Si utiliza un solo cliente para varios recursos, la limitación o las interrupciones asociadas a un recurso provocan un aumento de la latencia y los errores cuando el cliente accede a todos los demás recursos. Cuando utiliza la estrategia de reintento adaptativa es recomendable utilizar un único cliente para cada recurso.
También le recomendamos que utilice esta estrategia en situaciones en las que todos los clientes utilicen la estrategia de reintento adaptativa frente al recurso.
importante
La publicación de las estrategias de reintento con la versión 2.26.0 del SDK de Java incluye el nuevo valor de enumeración RetryMode.ADAPTIVE_V2ADAPTIVE_V2 corrige un error que no retrasaba el primer intento cuando se detectaban previamente errores de limitación.
Con la versión 2.26.0, los usuarios obtienen automáticamente el comportamiento del modo ADAPTIVE_V2 configurándolo como adaptive con una variable de entorno, una propiedad del sistema o un ajuste del perfil. Estos ajustes no tienen ningún valor adaptive_v2. Consulte la siguiente sección Especificación de una estrategia para aprender a configurar el modo.
Los usuarios pueden obtener el comportamiento anterior configurando el modo en código mediante RetryMode.ADAPTIVE.
Resumen: comparación de los valores predeterminados de la estrategia de reintento
En la tabla siguiente, se muestran los valores predeterminados de las propiedades de cada estrategia de reintento.
| Strategy (Estrategia) | Número máximo de intentos | Retraso base para errores sin limitación | Retraso base para errores con limitación | Tamaño del bucket de tokens | Costo del token por reintento sin limitación | Costo del token por reintento con limitación |
|---|---|---|---|---|---|---|
| Estándar | 3 | 100 ms | 1000 ms | 500 | 5 | 5 |
| Legacy | 4 | 100 ms | 500 ms | 500 | 5 | 0 |
| Adaptiva | 3 | 100 ms | 100 ms | 500 | 5 | 5 |
nota
Los clientes de DynamoDB utilizan un número máximo predeterminado de reintentos de 8 para todas las estrategias de reintento, que es superior a los valores que se muestran en la tabla anterior para otros clientes de Servicio de AWS.
Especificación de una estrategia
Hay cuatro formas de especificar una estrategia para el cliente de servicio.
En el código
Al crear un cliente, puede configurar una expresión lambda con una estrategia de reintento. El siguiente fragmento configura una estrategia de reintento estándar que utiliza valores predeterminados en un cliente de servicio de DynamoDB.
DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy(RetryMode.STANDARD)) .build();
Puede especificar RetryMode.LEGACY o RetryMode.ADAPTIVE en lugar de RetryMode.STANDARD.
Como ajuste de perfil
Incluya retry_mode como ajuste de perfil en el archivo de configuración de AWS compartido. Especifique standard, legacy o adaptive como valor. Cuando se establece como ajuste de perfil, todos los clientes de servicio que se creen mientras el perfil esté activo utilizarán la estrategia de reintento especificada con los valores predeterminados. Puede anular este ajuste configurando una estrategia de reintento en código, como se ha mostrado anteriormente.
Con el siguiente perfil, todos los clientes de servicio utilizan la estrategia de reintento estándar.
[profile dev] region = us-east-2 retry_mode = standard
Como propiedad del sistema JVM
Puede configurar una estrategia de reintento para todos los clientes de servicio, a menos que se anulen en el código, mediante la propiedad del sistema aws.retryMode. Especifique standard, legacy o adaptive como valor.
Utilice el conmutador -D cuando invoque Java, como se muestra en el siguiente comando.
java -Daws.retryMode=standard ...
También puede configurar la propiedad del sistema en el código antes de crear cualquier cliente, como se muestra en el siguiente fragmento.
public void main(String[] args) { // Set the property BEFORE any AWS service clients are created. System.setProperty("aws.retryMode", "standard"); ... }
Con una variable de entorno
También puede utilizar la variable de entorno AWS_RETRY_MODE con un valor de standard, legacy o adaptive. Al igual que ocurre con una configuración de perfil o una propiedad del sistema JVM, la variable de entorno configura todos los clientes de servicio con el modo de reintento especificado, a menos que se configure un cliente en el código.
El siguiente comando establece el modo de reintento en standard para la sesión actual del intérprete de comandos.
export AWS_RETRY_MODE=standard
Personalización de una estrategia
Puede personalizar cualquier estrategia de reintento estableciendo el número máximo de intentos, la estrategia de retroceso y las excepciones reintentables. Puede personalizar cuándo crea una estrategia de reintento o cuándo crea un cliente mediante un generador de anulaciones que permita seguir afinando la estrategia configurada.
Personalización de intentos máximos
Puede configurar el número máximo de intentos durante la creación del cliente, como se muestra en la siguiente instrucción. La siguiente instrucción personaliza la estrategia de reintento predeterminada para el cliente a un máximo de 5 intentos: un primer intento más 4 reintentos.
DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy(b -> b.maxAttempts(5))) .build();
Como alternativa, puede crear la estrategia y proporcionársela al cliente, como se muestra en el siguiente código de ejemplo. El código siguiente reemplaza el máximo estándar de 3 intentos por 10 y configura un cliente de DynamoDB con la estrategia personalizada.
StandardRetryStrategy strategy = AwsRetryStrategy.standardRetryStrategy() .toBuilder() .maxAttempts(10) .build(); DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy(strategy)) .build();
aviso
Se recomienda configurar cada cliente con una instancia de RetryStrategy única. Si se comparte una instancia de RetryStrategy, los errores de un cliente pueden afectar al comportamiento de reintento del otro.
También puede establecer el número máximo de intentos para todos los clientes mediante ajustes externos en lugar de código. Puede configurar este ajuste como se describe en la sección Especificación de una estrategia.
Personalización de excepciones reintentables
Puede configurar excepciones adicionales que activen los reintentos durante la creación del cliente. Esta personalización se proporciona para casos periféricos en los que se lancen excepciones que no estén incluidas en el conjunto predeterminado de excepciones reintentables.
Los métodos retryOnException y retryOnExceptionOrCause agregan nuevos tipos de excepciones al conjunto existente de excepciones reintentables; no sustituyen al conjunto predeterminado. Esto le permite ampliar el comportamiento de reintento y, al mismo tiempo, mantener las capacidades de reintento predeterminadas del SDK.
El método retryOnExceptionOrCause agrega una excepción reintentable si el SDK lanza la excepción directa o si la excepción se empaqueta como causa en otra excepción.
El siguiente fragmento de código muestra los métodos utilizados para personalizar las excepciones de reintento: retryOnException y retryOnExceptionOrCause. El método retryOnExceptionOrCause agrega una excepción reintentable si el SDK lanza la excepción directa o si la excepción está empaquetada.
DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy( b -> b.retryOnException(EdgeCaseException.class) .retryOnExceptionOrCause(WrappedEdgeCaseException.class))) .build();
importante
Los reintentos están deshabilitados para el cliente asincrónico de Kinesis cuando se llama a un método subscribeToShard
Personalización de la estrategia de retroceso
Puede crear la estrategia de retroceso y proporcionársela al cliente.
El siguiente código crea una BackoffStrategy que reemplaza la estrategia de retardo exponencial de la estrategia estándar predeterminada.
BackoffStrategy backoffStrategy = BackoffStrategy.exponentialDelay(Duration.ofMillis(150), // The base delay. Duration.ofSeconds(15)); // The maximum delay. DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(o -> o.retryStrategy( b -> b.backoffStrategy(backoffStrategy))) .build();
Migración desde RetryPolicy a RetryStrategy
RetryPolicy (la API de política de reintentos) recibirá soporte a lo largo de los próximos años. Si actualmente utiliza una instancia de RetryPolicy para configurar el cliente, todo funcionará como antes. Entre bastidores, el SDK de Java la adapta a una RetryStrategy. Las nuevas interfaces de las estrategias de reintento proporcionan la misma funcionalidad que una RetryPolicy, pero se crean y configuran de forma diferente.