En esta página, se describe cómo las herramientas de Cloud Storage reintentan las solicitudes fallidas y cómo personalizar el comportamiento de los reintentos. También se describen las consideraciones para reintentar las solicitudes.
Descripción general
Existen dos factores que determinan si una solicitud es segura o no:
- La respuesta que recibes de la solicitud
- La idempotencia de la solicitud.
Respuesta
La respuesta que recibes de tu solicitud indica si es útil reintentar la solicitud. Por lo general, las respuestas relacionadas con los problemas transitorios se pueden reintentar. Por otro lado, la respuesta relacionada con errores permanentes indica que debes realizar cambios, como cambios de autorización o configuración, antes de que sea útil reintentar la solicitud. Las siguientes respuestas indican problemas transitorios que son útiles para reintentar:
- Códigos de respuesta HTTP
408
,429
y5xx
. - Tiempos de espera de sockets agotados y desconexiones de TCP
Si quieres obtener más información, consulta los códigos de estado y error para JSON y XML.
Idempotencia
Una solicitud que es idempotente significa que se puede realizar de manera reiterada y que siempre deja el recurso de destino en el mismo estado final. Por ejemplo, las solicitudes de listas siempre son idempotentes, ya que estas solicitudes no modifican recursos. Por otro lado, crear una notificación de Pub/Sub nueva nunca es idempotente, ya que crea un ID de notificación nuevo cada vez que la solicitud se realiza de forma correcta.
Los siguientes son ejemplos de condiciones que hacen que una operación sea idempotente:
La operación tiene el mismo efecto observable en el recurso objetivo incluso cuando se solicita de forma continua.
La operación solo se realiza una vez.
La operación no tiene un efecto observable en el estado del recurso de destino.
Cuando recibes una respuesta que se puede reintentar, debes considerar la idempotencia de la solicitud, ya que reintentar solicitudes que no son idempotentes puede generar condiciones de carrera y otros conflictos.
Idempotencia condicional
Un subconjunto de solicitudes es condicionalmente idempotente, lo que significa que solo son idempotentes si incluyen argumentos opcionales específicos. Las operaciones condicionalmente seguras para su reintento solo deben reintentarse de forma predeterminada si se aprueba el caso de la condición. Cloud Storage acepta condiciones previas y ETag como casos de condición para las solicitudes.
Idempotencia de operaciones
En la siguiente tabla, se describen las operaciones de Cloud Storage que corresponden a cada categoría de idempotencia.
Idempotencia | Operaciones |
---|---|
Siempre idempotente |
|
Condicionalmente idempotente |
|
Nunca idempotente |
|
1 Este campo está disponible para su uso en la API de JSON. Para obtener información sobre los campos disponibles para usar en las bibliotecas cliente, consulta la documentación de las bibliotecas cliente relevante.
Cómo las herramientas de Cloud Storage implementan estrategias de reintento
Console
La consola de Google Cloud envía solicitudes a Cloud Storage en tu nombre y controla las retiradas necesarias.
Línea de comandos
Los comandos gcloud storage
vuelven a intentar los errores enumerados en
la sección Respuesta sin que debas realizar ninguna acción adicional.
Es posible que debas tomar medidas en caso de otros errores, como los siguientes:
Credenciales no válidas o permisos insuficientes.
No se puede acceder a la red debido a un problema de configuración del proxy.
Para los errores que se pueden intentar de nuevo, gcloud CLI vuelve a intentar las solicitudes a través de una estrategia de retirada exponencial binaria truncada. La cantidad predeterminada de reintentos máximos es 32 para la gcloud CLI.
Bibliotecas cliente
C++
De forma predeterminada, las operaciones admiten reintentos para los siguientes códigos de error de HTTP, así como cualquier error de socket que indique que se perdió la conexión o que nunca se estableció de forma correcta.
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Todas las opciones de retirada exponencial y de reintentos en la biblioteca de C++ se pueden configurar. Si los algoritmos implementados en la biblioteca no satisfacen tus necesidades, puedes proporcionar un código personalizado para implementar tus propias estrategias.
Configuración | Valor predeterminado |
---|---|
Reintento automático | True |
Tiempo máximo de reintentos de una solicitud | 15 minutos |
Tiempo de espera (retirada) inicial | 1 segundo |
Multiplicador de tiempo de espera por iteración | 2 |
Tiempo máximo de espera | 5 minutos |
Según la configuración predeterminada, la biblioteca de C++ reintenta todas las operaciones con errores que se pueden reintentar, incluso aquellas que nunca son idempotentes y pueden borrar o crear varios recursos cuando se realizan con éxito de forma repetida. Para reintentar solo las operaciones idempotentes, usa la clase google::cloud::storage::StrictIdempotencyPolicy
.
C#
La biblioteca cliente C# usa la retirada exponencial de forma predeterminada.
Go
De forma predeterminada, las operaciones admiten reintentos para los siguientes errores:
- Errores de conexión
io.ErrUnexpectedEOF
: Esto puede ocurrir debido a problemas transitorios de la red.url.Error
que contieneconnection refused
: Esto puede ocurrir debido a problemas transitorios de la red.url.Error
que contieneconnection reset by peer
: Esto significa que Google Cloud restableció la conexión.net.ErrClosed
: Esto significa que Google Cloud cerró la conexión.
- Códigos HTTP:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
- Errores que implementan la interfaz
Temporary()
y dan un valor deerr.Temporary() == true
- Cualquiera de los errores anteriores que se unieron a través de la unión de errores de Go 1.13
Todos los parámetros de configuración de retirada exponencial de la biblioteca GO se puede configurar. De forma predeterminada, las operaciones en Go usan la siguiente configuración para la retirada exponencial (los valores predeterminados se toman de gax):
Configuración | Valor predeterminado (en segundos) |
---|---|
Reintento automático | Verdadero si es idempotente |
Cantidad máxima de intentos | Sin límite |
Demora inicial hasta reintento | 1 segundo |
Multiplicador de demora de reintentos | 2.0 |
Retraso máximo de reintentos | 30 segundos |
Tiempo de espera total (fragmento de carga reanudable) | 32 segundos |
Tiempo de espera total (todas las demás operaciones) | Sin límite |
En general, los reintentos continúan de forma indefinida, a menos que se cancele el contexto de control, el cliente se cierre o se reciba un error no transitorio. Para evitar que los reintentos continúen, usa los tiempos de espera de contexto o la cancelación. La única excepción a este comportamiento es cuando se realizan cargas reanudables a través de Writer, en las que los datos son lo suficientemente grandes como para que se requieran varias solicitudes. En esta situación, cada fragmento agota el tiempo de espera y deja de reintentar después de 32 segundos de forma predeterminada. Puedes cambiar el tiempo de espera predeterminado si cambias Writer.ChunkRetryDeadline
.
Hay un subconjunto de operaciones de Go que son idempotentes de forma condicional (condicionalmente seguras para reintentar). Estas operaciones solo se reintentan si cumplen con condiciones específicas:
GenerationMatch
oGeneration
- Es seguro volver a intentarlo si se aplicó una condición previa
GenerationMatch
a la llamada o si se configuróObjectHandle.Generation
.
- Es seguro volver a intentarlo si se aplicó una condición previa
MetagenerationMatch
- Es seguro volver a intentarlo si se aplicó una condición previa
MetagenerationMatch
a la llamada.
- Es seguro volver a intentarlo si se aplicó una condición previa
Etag
- Es seguro reintentarlo si el método inserta un
etag
en el cuerpo de la solicitud JSON. Solo se usa enHMACKeyHandle.Update
cuando se estableceHmacKeyMetadata.Etag
.
- Es seguro reintentarlo si el método inserta un
RetryPolicy
se establece en RetryPolicy.RetryIdempotent
de forma predeterminada. Consulta Personaliza los reintentos para obtener ejemplos sobre cómo modificar el comportamiento de reintento predeterminado.
Java
De forma predeterminada, las operaciones admiten reintentos para los siguientes errores:
- Errores de conexión
Connection reset by peer
: Esto significa que Google Cloud restableció la conexión.Unexpected connection closure
: Esto significa que Google Cloud cerró la conexión.
- Códigos HTTP:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Todos los parámetros de configuración de retirada exponencial de la biblioteca Java se puede configurar. De forma predeterminada, las operaciones a través de Java usan la siguiente configuración para la retirada exponencial:
Configuración | Valor predeterminado (en segundos) |
---|---|
Reintento automático | Verdadero si es idempotente |
Cantidad máxima de intentos | 6 |
Demora inicial hasta reintento | 1 segundo |
Multiplicador de demora de reintentos | 2.0 |
Retraso máximo de reintentos | 32 segundos |
Tiempo de espera total | 50 segundos |
Tiempo de espera de RPC inicial | 50 segundos |
Multiplicador de tiempo de espera de RPC | 1.0 |
Tiempo de espera máximo de RPC | 50 segundos |
Se agotó el tiempo de espera de la conexión | 20 segundos |
Tiempo de espera de lectura | 20 segundos |
Si deseas obtener más información sobre la configuración, consulta la documentación de referencia de Java de RetrySettings.Builder
y HttpTransportOptions.Builder
.
Hay un subconjunto de operaciones de Java que son idempotentes de forma condicional (condicionalmente seguras para reintentar). Estas operaciones solo se reintentan si incluyen argumentos específicos:
ifGenerationMatch
ogeneration
- Es seguro reintentarlo si
ifGenerationMatch
ogeneration
se aprobaron como opción del método.
- Es seguro reintentarlo si
ifMetagenerationMatch
- Es seguro volver a intentarlo si
ifMetagenerationMatch
se pasó como una opción.
- Es seguro volver a intentarlo si
StorageOptions.setStorageRetryStrategy
se establece en StorageRetryStrategy#getDefaultStorageRetryStrategy
de forma predeterminada.
Consulta Personaliza los reintentos para obtener ejemplos sobre cómo modificar el comportamiento de reintento predeterminado.
Node.js
De forma predeterminada, las operaciones admiten reintentos para los siguientes códigos de error:
- Errores de conexión
EAI_again
: Este es un error de búsqueda de DNS. Para obtener más información, consulta la documentación degetaddrinfo
.Connection reset by peer
: Esto significa que Google Cloud restableció la conexión.Unexpected connection closure
: Esto significa que Google Cloud cerró la conexión.
- Códigos HTTP:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Toda la configuración de retirada exponencial de la biblioteca Node.js se puede configurar. De forma predeterminada, las operaciones a través de Node.js usan la siguiente configuración para la retirada exponencial:
Configuración | Valor predeterminado (en segundos) |
---|---|
Reintento automático | Verdadero si es idempotente |
Cantidad máxima de reintentos | 3 |
Tiempo de espera inicial | 1 segundo |
Multiplicador de tiempo de espera por iteración | 2 |
Tiempo máximo de espera | 64 segundos |
Plazo predeterminado | 600 segundos |
Hay un subconjunto de las operaciones Node.js que son idempotentes de forma condicional (condicionalmente seguro para reintentar). Estas operaciones solo se reintentan si incluyen argumentos específicos:
ifGenerationMatch
ogeneration
- Es seguro reintentarlo si
ifGenerationMatch
ogeneration
se aprobaron como opción del método. A menudo, los métodos solo aceptan uno de estos dos parámetros.
- Es seguro reintentarlo si
ifMetagenerationMatch
- Es seguro volver a intentarlo si
ifMetagenerationMatch
se pasó como una opción.
- Es seguro volver a intentarlo si
retryOptions.idempotencyStrategy
se establece en IdempotencyStrategy.RetryConditional
de forma predeterminada. Consulta Personaliza los reintentos para obtener ejemplos sobre cómo modificar el comportamiento de reintento predeterminado.
PHP
La biblioteca cliente de PHP usa la retirada exponencial de forma predeterminada.
Python
De forma predeterminada, las operaciones admiten reintentos para los siguientes códigos de error:
- Errores de conexión
requests.exceptions.ConnectionError
requests.exceptions.ChunkedEncodingError
(solo para operaciones que recuperan o envían datos de carga útil a objetos, como cargas y descargas)ConnectionError
- Códigos HTTP:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Las operaciones a través de Python usan la siguiente configuración predeterminada para la retirada exponencial:
Configuración | Valor predeterminado (en segundos) |
---|---|
Reintento automático | Verdadero si es idempotente |
Tiempo de espera inicial | 1 |
Multiplicador de tiempo de espera por iteración | 2 |
Tiempo máximo de espera | 60 |
Plazo predeterminado | 120 |
Existe un subconjunto de operaciones de Python que son idempotentes de forma condicional (condicionalmente seguras para reintentar) cuando incluyen argumentos específicos. Estas operaciones solo se reintentan si se aprueba un caso de condición:
DEFAULT_RETRY_IF_GENERATION_SPECIFIED
- Es seguro reintentarlo si
generation
oif_generation_match
se aprobaron como argumento del método. A menudo, los métodos solo aceptan uno de estos dos parámetros.
- Es seguro reintentarlo si
DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED
- Es seguro reintentarlo si
if_metageneration_match
se aprobó como argumento del método.
- Es seguro reintentarlo si
DEFAULT_RETRY_IF_ETAG_IN_JSON
- Es seguro reintentarlo si el método inserta un
etag
en el cuerpo de la solicitud JSON. ParaHMACKeyMetadata.update()
, esto significa que la ETag se debe configurar en el objetoHMACKeyMetadata
. Para el métodoset_iam_policy()
en otras clases, significa que la ETag se debe establecer en el argumento de la “política” que se pasó al método.
- Es seguro reintentarlo si el método inserta un
Ruby
De forma predeterminada, las operaciones admiten reintentos para los siguientes códigos de error:
- Errores de conexión
SocketError
HTTPClient::TimeoutError
Errno::ECONNREFUSED
HTTPClient::KeepAliveDisconnected
- Códigos HTTP:
408 Request Timeout
429 Too Many Requests
5xx Server Error
Todos los parámetros de configuración de retirada exponencial en la biblioteca cliente de Ruby se pueden configurar. De forma predeterminada, las operaciones a través de la biblioteca cliente de Ruby usan los siguientes parámetros de configuración para la retirada exponencial:
Configuración | Valor predeterminado |
---|---|
Reintento automático | True |
Cantidad máxima de reintentos | 3 |
Tiempo de espera inicial | 1 segundo |
Multiplicador de tiempo de espera por iteración | 2 |
Tiempo máximo de espera | 60 segundos |
Plazo predeterminado | 900 segundos |
Existe un subconjunto de operaciones de Ruby que son idempotentes de forma condicional (condicionalmente seguras para reintentar) cuando incluyen argumentos específicos:
if_generation_match
ogeneration
- Es seguro reintentarlo si el parámetro
generation
oif_generation_match
se pasa como un argumento al método. A menudo, los métodos solo aceptan uno de estos dos parámetros.
- Es seguro reintentarlo si el parámetro
if_metageneration_match
- Es seguro reintentarlo si el parámetro
if_metageneration_match
se pasa como una opción.
- Es seguro reintentarlo si el parámetro
Según la configuración predeterminada, se reintentan todas las operaciones idempotentes y las operaciones idempotentes de forma condicional se reintentan solo si se aprueba el caso de la condición. No se reintentan las operaciones que no son idempotentes. Consulta Personaliza los reintentos para obtener ejemplos sobre cómo modificar el comportamiento de reintento predeterminado.
API de REST
Cuando llames a la API de XML o JSON de forma directa, debes usar el algoritmo de retirada exponencial para implementar tu propia estrategia de reintento.
Personaliza los reintentos
Console
No puedes personalizar el comportamiento de los reintentos mediante la consola de Google Cloud.
Línea de comandos
Para los comandos de gcloud storage
, puedes controlar la estrategia de reintento si creas una configuración con nombre y configuras algunas o todas las siguientes propiedades:
base_retry_delay
exponential_sleep_multiplier
max_retries
max_retry_delay
Luego, debes aplicar la configuración definida por comando a través del uso de la marca--configuration
de todo el proyecto o para todos los comandos de gcloud con elcomando gcloud config set
.
Bibliotecas cliente
C++
Para personalizar el comportamiento de reintento, proporciona valores para las siguientes opciones cuando inicialices el objeto google::cloud::storage::Client
:
google::cloud::storage::RetryPolicyOption
: La biblioteca proporciona las clasesgoogle::cloud::storage::LimitedErrorCountRetryPolicy
ygoogle::cloud::storage::LimitedTimeRetryPolicy
. Puedes proporcionar tu propia clase, que debe implementar la interfazgoogle::cloud::RetryPolicy
.google::cloud::storage::BackoffPolicyOption
: La biblioteca proporciona la clasegoogle::cloud::storage::ExponentialBackoffPolicy
. Puedes proporcionar tu propia clase, que debe implementar la interfazgoogle::cloud::storage::BackoffPolicy
.google::cloud::storage::IdempotencyPolicyOption
: La biblioteca proporciona las clasesgoogle::cloud::storage::StrictIdempotencyPolicy
ygoogle::cloud::storage::AlwaysRetryIdempotencyPolicy
. Puedes proporcionar tu propia clase, que debe implementar la interfazgoogle::cloud::storage::IdempotencyPolicy
.
Si deseas obtener más información, consulta la documentación de referencia de la biblioteca cliente de C++.
C#
No puedes personalizar la estrategia de reintento predeterminada que usa la biblioteca cliente de C#.
Go
Cuando inicializas un cliente de almacenamiento, se establece una configuración de reintento predeterminada. A menos que se anulen, las opciones en la configuración se establecen en los valores predeterminados. Los usuarios pueden configurar el comportamiento de reintento no predeterminado para una sola llamada a la biblioteca (a través de BucketHandle.Retryer y ObjectHandle.Retryer) o para todas las llamadas que realiza un cliente (a través de Client.SetRetry). Para modificar el comportamiento de reintento, pasa las RetryOptions releventes a uno de estos métodos.
Consulta la siguiente muestra de código para aprender cómo personalizar tu comportamiento de reintento.
Java
Cuando inicializas Storage
, también se inicializa una instancia de RetrySettings
. A menos que se anulen, las opciones de RetrySettings
se establecen con los valores predeterminados. Para modificar el comportamiento de reintento automático predeterminado, pasa la StorageRetryStrategy
personalizada a las StorageOptions
que se usan para construir la instancia de Storage
. Si deseas modificar cualquiera de los otros parámetros escalares, pasa una RetrySettings
personalizada a las StorageOptions
que se usan para construir la instancia de Storage
.
Consulta el siguiente ejemplo para aprender cómo personalizar el comportamiento de reintento:
Node.js
Cuando inicializas Cloud Storage, también se inicializa un archivo de configuración retryOptions. A menos que se anulen, las opciones en la configuración se establecen en los valores predeterminados. Para modificar el comportamiento de reintento predeterminado, pasa la configuración de reintento personalizada retryOptions
al constructor de almacenamiento durante la inicialización.
La biblioteca cliente de Node.js puede usar estrategias de retirada de forma automática para reintentar solicitudes con el parámetro autoRetry
.
Consulta la siguiente muestra de código para aprender cómo personalizar tu comportamiento de reintento.
PHP
No puedes personalizar la estrategia de reintento predeterminada que usa la biblioteca cliente de PHP.
Python
Para modificar el comportamiento de reintento predeterminado, crea una copia del objeto google.cloud.storage.retry.DEFAULT_RETRY
llamándolo con un método with_XXX
. La biblioteca cliente de Python usa estrategias de retirada de forma automática para reintentar las solicitudes si incluyes el parámetro DEFAULT_RETRY
.
Ten en cuenta que with_predicate
no es compatible con operaciones que recuperan o envían datos de carga útil a objetos, como cargas y descargas. Te recomendamos modificar los atributos uno por uno. Para obtener más información, consulta la referencia de operaciones de reintento de google-api-core.
Para configurar tu propio reintento condicional, crea un objeto ConditionalRetryPolicy
y une tu objeto Retry
personalizado con DEFAULT_RETRY_IF_GENERATION_SPECIFIED
, DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED
o DEFAULT_RETRY_IF_ETAG_IN_JSON
.
Consulta la siguiente muestra de código para aprender cómo personalizar tu comportamiento de reintento.
Ruby
Cuando inicializas el cliente de almacenamiento, todas las opciones de configuración de reintentos se establecen en los valores que se muestran en la tabla anterior. Para modificar el comportamiento de reintento predeterminado, pasa las opciones de configuración de reintento mientras inicializas el cliente de almacenamiento.
Para anular la cantidad de reintentos de una operación en particular, pasa retries
en el parámetro options
de la operación.
API de REST
Usa el algoritmo de retirada exponencial para implementar tu propia estrategia de reintento.
Algoritmo de retirada exponencial
Un algoritmo de retirada exponencial reintenta las solicitudes a través del aumento exponencial de los tiempos de espera entre solicitudes, hasta un tiempo de retirada máximo. Por lo general, debes usar la retirada exponencial con jitter para reintentar las solicitudes que cumplan con los criterios de respuesta y de idempotencia. Para obtener prácticas recomendadas sobre la implementación de reintentos automáticos con retirada exponencial, consulta Aborda fallas en cascada.
¿Qué sigue?
- Obtén información para reintentar solicitudes en el Servicio de transferencia de almacenamiento con Java o Python.
- Obtén más información de las condiciones previas de solicitud.