Estratégia de repetição

Esta página descreve como as ferramentas do Cloud Storage repetem os pedidos com falhas e como personalizar o comportamento das repetições. Também descreve as considerações para repetir pedidos.

Vista geral

Existem dois fatores que determinam se um pedido é seguro para repetir:

  • A resposta que recebe do pedido.

  • A idempotência do pedido.

Resposta

A resposta que recebe da sua solicitação indica se é útil ou não tentar novamente a solicitação. As respostas relacionadas com problemas transitórios são, geralmente, repetíveis. Por outro lado, as respostas relacionadas com erros permanentes indicam que tem de fazer alterações, como alterações de autorização ou configuração, antes de ser útil tentar o pedido novamente. As seguintes respostas indicam problemas transitórios que são úteis para tentar novamente:

  • Códigos de resposta HTTP 408, 429 e 5xx.
  • Tempos limite de entrada e desligamentos de TCP.

Para mais informações, consulte o estado e os códigos de erro para JSON e XML.

Idempotência

Os pedidos idempotentes podem ser executados repetidamente sem alterar o estado final do recurso segmentado, o que resulta no mesmo estado final todas as vezes. Por exemplo, as operações de listas são sempre idempotentes porque esses pedidos não modificam os recursos. Por outro lado, a criação de uma nova notificação do Pub/Sub nunca é idempotente, porque cria um novo ID de notificação sempre que o pedido é bem-sucedido.

Seguem-se alguns exemplos de condições que tornam uma operação idempotente:

  • A operação tem o mesmo efeito observável no recurso segmentado, mesmo quando solicitada continuamente.

  • A operação só é bem-sucedida uma vez.

  • A operação não tem um efeito observável no estado do recurso segmentado.

Quando recebe uma resposta repetível, deve considerar a idempotência do pedido, porque a repetição de pedidos que não são idempotentes pode originar condições de concorrência e outros conflitos.

Idempotência condicional

Um subconjunto de pedidos é condicionalmente idempotente, o que significa que só é idempotente se incluir argumentos opcionais específicos. As operações que são condicionalmente seguras para repetir só devem ser repetidas por predefinição se a condição for aprovada. O Cloud Storage aceita pré-condições e ETags como casos de condições para pedidos.

Idempotência das operações

A tabela seguinte apresenta as operações do Cloud Storage que se enquadram em cada categoria de idempotência.

Idempotência Operações
Sempre idempotente
  • Todos os pedidos de obtenção e listagem
  • Insira ou elimine contentores
  • Teste as políticas e as autorizações de IAM do contentor
  • Bloqueie políticas de retenção
  • Elimine uma chave HMAC ou uma notificação do Pub/Sub
Condicionalmente idempotente
  • Pedidos de atualização/patch para contentores com IfMetagenerationMatch1 ou etag1 como pré-condição HTTP
  • Pedidos de atualização/patch para objetos com IfMetagenerationMatch1 ou etag1 como pré-condição HTTP
  • Defina uma Política IAM do contentor com etag1 como pré-condição HTTP ou no corpo do recurso
  • Atualize uma chave HMAC com etag1 como pré-condição HTTP ou no corpo do recurso
  • Inserir, copiar, compor ou reescrever objetos com o ifGenerationMatch1
  • Elimine um objeto com ifGenerationMatch1 (ou com um número de geração para versões de objetos)
Nunca idempotente
  • Crie uma chave HMAC
  • Crie uma notificação do Pub/Sub
  • Criar, eliminar ou enviar pedidos de patch/atualização para LCAs de objetos e de contentores ou LCAs de objetos predefinidas

1Este campo está disponível para utilização na API JSON. Para ver os campos disponíveis para utilização nas bibliotecas cliente, consulte a documentação da biblioteca cliente relevante.

Como as ferramentas do Cloud Storage implementam estratégias de repetição

Consola

A consola envia pedidos ao Cloud Storage em seu nome e processa qualquer recuo necessário. Google Cloud

Linha de comandos

Os comandos gcloud storage tentam novamente os erros indicados na secção Resposta sem que tenha de realizar ações adicionais. Pode ter de tomar medidas para outros erros, como os seguintes:

  • Credenciais inválidas ou autorizações insuficientes.

  • Rede inacessível devido a um problema de configuração do proxy.

Para erros repetíveis, a CLI gcloud tenta novamente os pedidos através de uma estratégia de retirada exponencial binária truncada. O número predefinido de tentativas máximas é 32 para a CLI gcloud.

Bibliotecas cliente

C++

Por predefinição, as operações suportam novas tentativas para os seguintes códigos de erro HTTP, bem como quaisquer erros de socket que indiquem que a ligação foi perdida ou nunca estabelecida com êxito.

  • 408 Request Timeout
  • 429 Too Many Requests
  • 500 Internal Server Error
  • 502 Bad Gateway
  • 503 Service Unavailable
  • 504 Gateway Timeout

Todas as definições de repetição e recuo exponencial na biblioteca C++ são configuráveis. Se os algoritmos implementados na biblioteca não satisfizerem as suas necessidades, pode fornecer código personalizado para implementar as suas próprias estratégias.

Definição Valor predefinido
Nova tentativa automática True
Tempo máximo para repetir um pedido 15 minutos
Tempo de espera inicial (recuo) 1 segundo
Multiplicador do tempo de espera por iteração 2
Tempo de espera máximo 5 minutos

Por predefinição, a biblioteca C++ tenta novamente todas as operações com erros repetíveis, mesmo as que nunca são idempotentes e podem eliminar ou criar vários recursos quando são bem-sucedidas repetidamente. Para repetir apenas operações idempotentes, use a classe google::cloud::storage::StrictIdempotencyPolicy.

C#

A biblioteca cliente C# usa a retirada exponencial por predefinição.

Go

Por predefinição, as operações suportam novas tentativas para os seguintes erros:

  • Erros de ligação:
    • io.ErrUnexpectedEOF: isto pode ocorrer devido a problemas de rede temporários.
    • url.Error com connection refused: isto pode ocorrer devido a problemas de rede temporários.
    • url.Error que contém connection reset by peer: Isto significa que Google Cloud repôs a ligação.
    • net.ErrClosed: Isto significa que Google Cloud fechou a ligação.
  • Códigos HTTP:
    • 408 Request Timeout
    • 429 Too Many Requests
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Erros que implementam a interface Temporary() e dão um valor de err.Temporary() == true
  • Qualquer um dos erros acima que tenha sido envolvido através da envolvente de erros do Go 1.13

Todas as definições de recuo exponencial na biblioteca Go são configuráveis. Por predefinição, as operações em Go usam as seguintes definições para a retirada exponencial (as predefinições são retiradas de gax):

Definição Valor predefinido (em segundos)
Nova tentativa automática Verdadeiro se for idempotente
Número máximo de tentativas Sem limite
Atraso inicial da nova tentativa 1 segundo
Multiplicador do atraso da repetição 2,0
Atraso máximo de repetição 30 segundos
Tempo limite total (fragmento de carregamento retomável) 32 segundos
Tempo limite total (todas as outras operações) Sem limite

Em geral, a repetição continua indefinidamente, a menos que o contexto de controlo seja cancelado, o cliente seja fechado ou seja recebido um erro não transitório. Para impedir que as novas tentativas continuem, use os limites de tempo de contexto ou o cancelamento. A única exceção a este comportamento ocorre quando faz carregamentos retomáveis através do Writer, em que os dados são suficientemente grandes para exigirem vários pedidos. Neste cenário, cada bloco excede o tempo limite e deixa de tentar novamente após 32 segundos por predefinição. Pode ajustar o limite de tempo predefinido alterando Writer.ChunkRetryDeadline.

Existe um subconjunto de operações Go que são condicionalmente idempotentes (condicionalmente seguras para repetir). Estas operações só são repetidas se cumprir condições específicas:

  • GenerationMatch ou Generation

    • É seguro tentar novamente se uma pré-condição GenerationMatch tiver sido aplicada à chamada ou se ObjectHandle.Generation tiver sido definida.
  • MetagenerationMatch

    • É seguro tentar novamente se tiver sido aplicada uma condição prévia do MetagenerationMatch à chamada.
  • Etag

    • É seguro tentar novamente se o método inserir um etag no corpo do pedido JSON. Usado apenas em HMACKeyHandle.Update quando HmacKeyMetadata.Etag foi definido.

Por predefinição, a definição de RetryPolicy é RetryPolicy.RetryIdempotent. Consulte o artigo Personalizar novas tentativas para ver exemplos de como modificar o comportamento de novas tentativas predefinido.

Java

Por predefinição, as operações suportam novas tentativas para os seguintes erros:

  • Erros de ligação:
    • Connection reset by peer: isto significa que Google Cloud repôs a ligação.
    • Unexpected connection closure: isto significa que Google Cloud fechou a ligação.
  • Códigos HTTP:
    • 408 Request Timeout
    • 429 Too Many Requests
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout

Todas as definições de recuo exponencial na biblioteca Java são configuráveis. Por predefinição, as operações através de Java usam as seguintes definições para a repetição exponencial:

Definição Valor predefinido (em segundos)
Nova tentativa automática Verdadeiro se for idempotente
Número máximo de tentativas 6
Atraso inicial da nova tentativa 1 segundo
Multiplicador do atraso da repetição 2,0
Atraso máximo de repetição 32 segundos
Tempo limite total 50 segundos
Limite de tempo da RPC inicial 50 segundos
Multiplicador de limite de tempo de RPC 1,0
Limite de tempo máximo de RPC 50 segundos
Limite de tempo da ligação 20 segundos
Tempo limite de leitura 20 segundos

Para mais informações sobre as definições, consulte a documentação de referência do Java para RetrySettings.Builder e HttpTransportOptions.Builder.

Existe um subconjunto de operações Java que são condicionalmente idempotentes (condicionalmente seguras para repetir). Estas operações só são repetidas se incluírem argumentos específicos:

  • ifGenerationMatch ou generation

    • É seguro tentar novamente se ifGenerationMatch ou generation tiver sido transmitido como uma opção para o método.
  • ifMetagenerationMatch

    • É seguro tentar novamente se ifMetagenerationMatch tiver sido transmitido como uma opção.

StorageOptions.setStorageRetryStrategy está definido como StorageRetryStrategy#getDefaultStorageRetryStrategy por predefinição. Consulte o artigo Personalizar novas tentativas para ver exemplos de como modificar o comportamento de novas tentativas predefinido.

Node.js

Por predefinição, as operações suportam novas tentativas para os seguintes códigos de erro:

  • Erros de ligação:
    • EAI_again: trata-se de um erro de procura de DNS. Para mais informações, consulte a documentação do getaddrinfo.
    • Connection reset by peer: isto significa que Google Cloud repôs a ligação.
    • Unexpected connection closure: isto significa que Google Cloud fechou a ligação.
  • Códigos HTTP:
    • 408 Request Timeout
    • 429 Too Many Requests
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout

Todas as definições de recuo exponencial na biblioteca Node.js são configuráveis. Por predefinição, as operações através do Node.js usam as seguintes definições para a retirada exponencial:

Definição Valor predefinido (em segundos)
Nova tentativa automática Verdadeiro se for idempotente
Número máximo de tentativas 3
Tempo de espera inicial 1 segundo
Multiplicador do tempo de espera por iteração 2
Tempo de espera máximo 64 segundos
Prazo predefinido 600 segundos

Existe um subconjunto de operações Node.js que são condicionalmente idempotentes (condicionalmente seguras para repetir). Estas operações só são repetidas se incluírem argumentos específicos:

  • ifGenerationMatch ou generation

    • É seguro tentar novamente se ifGenerationMatch ou generation tiver sido transmitido como uma opção para o método. Muitas vezes, os métodos só aceitam um destes dois parâmetros.
  • ifMetagenerationMatch

    • É seguro tentar novamente se ifMetagenerationMatch tiver sido transmitido como uma opção.

retryOptions.idempotencyStrategy está definido como IdempotencyStrategy.RetryConditional por predefinição. Consulte o artigo Personalizar novas tentativas para ver exemplos de como modificar o comportamento de novas tentativas predefinido.

PHP

A biblioteca cliente PHP usa a retirada exponencial por predefinição.

Por predefinição, as operações suportam novas tentativas para os seguintes códigos de erro:

  • Erros de ligação:
    • connetion-refused: isto pode ocorrer devido a problemas de rede temporários.
    • connection-reset: isto significa que Google Cloud repôs a ligação.
  • Códigos HTTP:
    • 200: para casos de transferências parciais
    • 408 Request Timeout
    • 429 Too Many Requests
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout

Algumas definições de recuo exponencial na biblioteca PHP são configuráveis. Por predefinição, as operações através do PHP usam as seguintes definições para a repetição exponencial:

Definição Valor predefinido (em segundos)
Nova tentativa automática Verdadeiro se for idempotente
Atraso inicial da nova tentativa 1 segundo
Multiplicador do atraso da repetição 2,0
Atraso máximo de repetição 60 segundos
Tempo limite de pedido 0 com REST, 60 com gRPC
Número predefinido de novas tentativas 3

Existe um subconjunto de operações PHP que são condicionalmente idempotentes (condicionalmente seguras para repetir). Estas operações só são repetidas se incluírem argumentos específicos:

  • ifGenerationMatch ou generation

    • É seguro tentar novamente se ifGenerationMatch ou generation tiver sido transmitido como uma opção para o método. Muitas vezes, os métodos só aceitam um destes dois parâmetros.
  • ifMetagenerationMatch

    • É seguro tentar novamente se ifMetagenerationMatch tiver sido transmitido como uma opção.

Quando cria StorageClient, a estratégia StorageClient::RETRY_IDEMPOTENT é usada por predefinição. Consulte o artigo Personalizar novas tentativas para ver exemplos de como modificar o comportamento de novas tentativas predefinido.

Python

Por predefinição, as operações suportam novas tentativas para os seguintes códigos de erro:

  • Erros de ligação:
    • requests.exceptions.ConnectionError
    • requests.exceptions.ChunkedEncodingError (apenas para operações que obtenham ou enviem dados de payload para objetos, como carregamentos e transferências)
    • ConnectionError
    • http.client.ResponseNotReady
    • urllib3.exceptions.TimeoutError
  • Códigos HTTP:
    • 408 Request Timeout
    • 429 Too Many Requests
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout

As operações através do Python usam as seguintes predefinições para a retirada exponencial:

Definição Valor predefinido (em segundos)
Nova tentativa automática Verdadeiro se for idempotente
Tempo de espera inicial 1
Multiplicador do tempo de espera por iteração 2
Tempo de espera máximo 60
Prazo predefinido 120

Além das operações do Cloud Storage que são sempre idempotentes, a biblioteca cliente Python tenta automaticamente as operações Objects: insert, Objects: delete e Objects: patch por predefinição.

Existe um subconjunto de operações Python que são condicionalmente idempotentes (condicionalmente seguras para repetir) quando incluem argumentos específicos. Estas operações só são repetidas se um caso de condição for aprovado:

  • DEFAULT_RETRY_IF_GENERATION_SPECIFIED

    • É seguro tentar novamente se generation ou if_generation_match tiver sido transmitido como argumento ao método. Muitas vezes, os métodos só aceitam um destes dois parâmetros.
  • DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED

    • É seguro tentar novamente se if_metageneration_match tiver sido transmitido como um argumento para o método.
  • DEFAULT_RETRY_IF_ETAG_IN_JSON

    • É seguro tentar novamente se o método inserir um etag no corpo do pedido JSON. Para HMACKeyMetadata.update(), isto significa que o etag tem de ser definido no próprio objeto HMACKeyMetadata. Para o método set_iam_policy() em outras classes, isto significa que o etag tem de ser definido no argumento "policy" transmitido para o método.

Ruby

Por predefinição, as operações suportam novas tentativas para os seguintes códigos de erro:

  • Erros de ligação:
    • SocketError
    • HTTPClient::TimeoutError
    • Errno::ECONNREFUSED
    • HTTPClient::KeepAliveDisconnected
  • Códigos HTTP:
    • 408 Request Timeout
    • 429 Too Many Requests
    • 5xx Server Error

Todas as definições de recuo exponencial na biblioteca cliente Ruby são configuráveis. Por predefinição, as operações através da biblioteca cliente Ruby usam as seguintes definições para o recuo exponencial:

Definição Valor predefinido
Nova tentativa automática True
Número máximo de tentativas 3
Tempo de espera inicial 1 segundo
Multiplicador do tempo de espera por iteração 2
Tempo de espera máximo 60 segundos
Prazo predefinido 900 segundos

Existe um subconjunto de operações Ruby que são condicionalmente idempotentes (condicionalmente seguras para repetir) quando incluem argumentos específicos:

  • if_generation_match ou generation

    • É seguro tentar novamente se o parâmetro generation ou if_generation_match for transmitido como um argumento para o método. Muitas vezes, os métodos só aceitam um destes dois parâmetros.
  • if_metageneration_match

    • É seguro tentar novamente se o parâmetro if_metageneration_match for transmitido como uma opção.

Por predefinição, todas as operações idempotentes são repetidas e as operações condicionalmente idempotentes só são repetidas se o caso da condição for aprovado. As operações não idempotentes não são repetidas. Consulte o artigo Personalizar novas tentativas para ver exemplos de como modificar o comportamento de novas tentativas predefinido.

APIs REST

Quando chamar a API JSON ou XML diretamente, deve usar o algoritmo de retirada exponencial para implementar a sua própria estratégia de repetição.

Personalizar novas tentativas

Consola

Não pode personalizar o comportamento das novas tentativas através da Google Cloud consola.

Linha de comandos

Para comandos gcloud storage, pode controlar a estratégia de repetição através da criação de uma configuração com nome e da definição de algumas ou todas as seguintes propriedades:

Definição Valor predefinido (em segundos)
base_retry_delay 1
exponential_sleep_multiplier 2
max_retries 32
max_retry_delay 32

Em seguida, aplica a configuração definida por comando através da --configurationflag ao nível do projeto ou a todos os comandos da CLI gcloud através do gcloud config set comando.

Bibliotecas cliente

C++

Para personalizar o comportamento de repetição, forneça valores para as seguintes opções quando inicializar o objeto google::cloud::storage::Client:

  • google::cloud::storage::RetryPolicyOption: a biblioteca oferece aulas de google::cloud::storage::LimitedErrorCountRetryPolicy e google::cloud::storage::LimitedTimeRetryPolicy. Pode fornecer a sua própria classe, que tem de implementar a interface google::cloud::RetryPolicy.

  • google::cloud::storage::BackoffPolicyOption: a biblioteca fornece a classe google::cloud::storage::ExponentialBackoffPolicy. Pode fornecer a sua própria classe, que tem de implementar a interface google::cloud::storage::BackoffPolicy.

  • google::cloud::storage::IdempotencyPolicyOption: a biblioteca disponibiliza as classes google::cloud::storage::StrictIdempotencyPolicy e google::cloud::storage::AlwaysRetryIdempotencyPolicy. Pode fornecer a sua própria classe, que tem de implementar a interface google::cloud::storage::IdempotencyPolicy.

Para mais informações, consulte a documentação de referência da biblioteca de cliente C++.

namespace gcs = ::google::cloud::storage;
// Create the client configuration:
auto options = google::cloud::Options{};
// Retries only idempotent operations.
options.set<gcs::IdempotencyPolicyOption>(
    gcs::StrictIdempotencyPolicy().clone());
// On error, it backs off for a random delay between [1, 3] seconds, then [3,
// 9] seconds, then [9, 27] seconds, etc. The backoff time never grows larger
// than 1 minute.
options.set<gcs::BackoffPolicyOption>(
    gcs::ExponentialBackoffPolicy(
        /*initial_delay=*/std::chrono::seconds(1),
        /*maximum_delay=*/std::chrono::minutes(1),
        /*scaling=*/3.0)
        .clone());
// Retries all operations for up to 5 minutes, including any backoff time.
options.set<gcs::RetryPolicyOption>(
    gcs::LimitedTimeRetryPolicy(std::chrono::minutes(5)).clone());
return gcs::Client(std::move(options));

C#

Não pode personalizar a estratégia de repetição predefinida usada pela biblioteca de cliente C#.

Go

Quando inicializa um cliente de armazenamento, é definida uma configuração de repetição predefinida. A menos que sejam substituídas, as opções na configuração são definidas com os valores predefinidos. Os utilizadores podem configurar o comportamento de repetição não predefinido para uma única chamada de biblioteca (através de BucketHandle.Retryer e ObjectHandle.Retryer) ou para todas as chamadas feitas por um cliente (através de Client.SetRetry). Para modificar o comportamento de repetição, transmita as RetryOptions relevantes a um destes métodos.

Consulte o seguinte exemplo de código para saber como personalizar o comportamento de repetição.

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/storage"
	"github.com/googleapis/gax-go/v2"
)

// configureRetries configures a custom retry strategy for a single API call.
func configureRetries(w io.Writer, bucket, object string) error {
	// bucket := "bucket-name"
	// object := "object-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %w", err)
	}
	defer client.Close()

	// Configure retries for all operations using this ObjectHandle. Retries may
	// also be configured on the BucketHandle or Client types.
	o := client.Bucket(bucket).Object(object).Retryer(
		// Use WithBackoff to control the timing of the exponential backoff.
		storage.WithBackoff(gax.Backoff{
			// Set the initial retry delay to a maximum of 2 seconds. The length of
			// pauses between retries is subject to random jitter.
			Initial: 2 * time.Second,
			// Set the maximum retry delay to 60 seconds.
			Max: 60 * time.Second,
			// Set the backoff multiplier to 3.0.
			Multiplier: 3,
		}),
		// Use WithPolicy to customize retry so that all requests are retried even
		// if they are non-idempotent.
		storage.WithPolicy(storage.RetryAlways),
	)

	// Use context timeouts to set an overall deadline on the call, including all
	// potential retries.
	ctx, cancel := context.WithTimeout(ctx, 500*time.Second)
	defer cancel()

	// Delete an object using the specified retry policy.
	if err := o.Delete(ctx); err != nil {
		return fmt.Errorf("Object(%q).Delete: %w", object, err)
	}
	fmt.Fprintf(w, "Blob %v deleted with a customized retry strategy.\n", object)
	return nil
}

Java

Quando inicializa Storage, também é inicializada uma instância de RetrySettings. A menos que sejam substituídas, as opções em RetrySettings são definidas com os valores predefinidos. Para modificar o comportamento de repetição automática predefinido, transmita o StorageRetryStrategy personalizado para o StorageOptions usado para construir a instância Storage. Para modificar qualquer um dos outros parâmetros escalares, transmita um RetrySettings personalizado para o StorageOptions usado para construir a instância Storage.

Consulte o exemplo seguinte para saber como personalizar o comportamento de repetição:


import com.google.api.gax.retrying.RetrySettings;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.storage.StorageRetryStrategy;
import org.threeten.bp.Duration;

public final class ConfigureRetries {
  public static void main(String[] args) {
    String bucketName = "my-bucket";
    String blobName = "blob/to/delete";
    deleteBlob(bucketName, blobName);
  }

  static void deleteBlob(String bucketName, String blobName) {
    // Customize retry behavior
    RetrySettings retrySettings =
        StorageOptions.getDefaultRetrySettings().toBuilder()
            // Set the max number of attempts to 10 (initial attempt plus 9 retries)
            .setMaxAttempts(10)
            // Set the backoff multiplier to 3.0
            .setRetryDelayMultiplier(3.0)
            // Set the max duration of all attempts to 5 minutes
            .setTotalTimeout(Duration.ofMinutes(5))
            .build();

    StorageOptions alwaysRetryStorageOptions =
        StorageOptions.newBuilder()
            // Customize retry so all requests are retried even if they are non-idempotent.
            .setStorageRetryStrategy(StorageRetryStrategy.getUniformStorageRetryStrategy())
            // provide the previously configured retrySettings
            .setRetrySettings(retrySettings)
            .build();

    // Instantiate a client
    Storage storage = alwaysRetryStorageOptions.getService();

    // Delete the blob
    BlobId blobId = BlobId.of(bucketName, blobName);
    boolean success = storage.delete(blobId);

    System.out.printf(
        "Deletion of Blob %s completed %s.%n", blobId, success ? "successfully" : "unsuccessfully");
  }
}

Node.js

Quando inicializa o Cloud Storage, também é inicializado um ficheiro de configuração retryOptions. A menos que sejam substituídas, as opções na configuração são definidas com os valores predefinidos. Para modificar o comportamento de repetição predefinido, transmita a configuração de repetição personalizada retryOptions ao construtor de armazenamento na inicialização. A biblioteca cliente Node.js pode usar automaticamente estratégias de recuo para repetir pedidos com o parâmetro autoRetry.

Consulte o seguinte exemplo de código para saber como personalizar o comportamento de repetição.

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

// The ID of your GCS file
// const fileName = 'your-file-name';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage({
  retryOptions: {
    // If this is false, requests will not retry and the parameters
    // below will not affect retry behavior.
    autoRetry: true,
    // The multiplier by which to increase the delay time between the
    // completion of failed requests, and the initiation of the subsequent
    // retrying request.
    retryDelayMultiplier: 3,
    // The total time between an initial request getting sent and its timeout.
    // After timeout, an error will be returned regardless of any retry attempts
    // made during this time period.
    totalTimeout: 500,
    // The maximum delay time between requests. When this value is reached,
    // retryDelayMultiplier will no longer be used to increase delay time.
    maxRetryDelay: 60,
    // The maximum number of automatic retries attempted before returning
    // the error.
    maxRetries: 5,
    // Will respect other retry settings and attempt to always retry
    // conditionally idempotent operations, regardless of precondition
    idempotencyStrategy: IdempotencyStrategy.RetryAlways,
  },
});
console.log(
  'Functions are customized to be retried according to the following parameters:'
);
console.log(`Auto Retry: ${storage.retryOptions.autoRetry}`);
console.log(
  `Retry delay multiplier: ${storage.retryOptions.retryDelayMultiplier}`
);
console.log(`Total timeout: ${storage.retryOptions.totalTimeout}`);
console.log(`Maximum retry delay: ${storage.retryOptions.maxRetryDelay}`);
console.log(`Maximum retries: ${storage.retryOptions.maxRetries}`);
console.log(
  `Idempotency strategy: ${storage.retryOptions.idempotencyStrategy}`
);

async function deleteFileWithCustomizedRetrySetting() {
  await storage.bucket(bucketName).file(fileName).delete();
  console.log(`File ${fileName} deleted with a customized retry strategy.`);
}

deleteFileWithCustomizedRetrySetting();

PHP

Quando inicializa um cliente de armazenamento, é definida uma configuração de repetição predefinida. A menos que sejam substituídas, as opções na configuração são definidas com os valores predefinidos. Os utilizadores podem configurar o comportamento de repetição não predefinido para um cliente ou uma única chamada de operação transmitindo opções de substituição numa matriz.

Consulte o seguinte exemplo de código para saber como personalizar o comportamento de repetição.

use Google\Cloud\Storage\StorageClient;

/**
 * Configures retries with customizations.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 */
function configure_retries(string $bucketName): void
{
    $storage = new StorageClient([
        // The maximum number of automatic retries attempted before returning
        // the error.
        // Default: 3
        'retries' => 10,

        // Exponential backoff settings
        // Retry strategy to signify that we never want to retry an operation
        // even if the error is retryable.
        // Default: StorageClient::RETRY_IDEMPOTENT
        'retryStrategy' => StorageClient::RETRY_ALWAYS,

        // Executes a delay
        // Defaults to utilizing `usleep`.
        // Function signature should match: `function (int $delay) : void`.
        // This function is mostly used internally, so the tests don't wait
        // the time of the delay to run.
        'restDelayFunction' => function ($delay) {
            usleep($delay);
        },

        // Sets the conditions for determining how long to wait between attempts to retry.
        // Function signature should match: `function (int $attempt) : int`.
        // Allows to change the initial retry delay, retry delay multiplier and maximum retry delay.
        'restCalcDelayFunction' => fn ($attempt) => ($attempt + 1) * 100,

        // Sets the conditions for whether or not a request should attempt to retry.
        // Function signature should match: `function (\Exception $ex) : bool`.
        'restRetryFunction' => function (\Exception $e) {
            // Custom logic: ex. only retry if the error code is 404.
            return $e->getCode() === 404;
        },

        // Runs after the restRetryFunction. This might be used to simply consume the
        // exception and $arguments b/w retries. This returns the new $arguments thus allowing
        // modification on demand for $arguments. For ex: changing the headers in b/w retries.
        'restRetryListener' => function (\Exception $e, $retryAttempt, &$arguments) {
            // logic
        },
    ]);
    $bucket = $storage->bucket($bucketName);
    $operationRetriesOverrides = [
        // The maximum number of automatic retries attempted before returning
        // the error.
        // Default: 3
        'retries' => 10,

        // Exponential backoff settings
        // Retry strategy to signify that we never want to retry an operation
        // even if the error is retryable.
        // Default: StorageClient::RETRY_IDEMPOTENT
        'retryStrategy' => StorageClient::RETRY_ALWAYS,

        // Executes a delay
        // Defaults to utilizing `usleep`.
        // Function signature should match: `function (int $delay) : void`.
        // This function is mostly used internally, so the tests don't wait
        // the time of the delay to run.
        'restDelayFunction' => function ($delay) {
            usleep($delay);
        },

        // Sets the conditions for determining how long to wait between attempts to retry.
        // Function signature should match: `function (int $attempt) : int`.
        // Allows to change the initial retry delay, retry delay multiplier and maximum retry delay.
        'restCalcDelayFunction' => fn ($attempt) => ($attempt + 1) * 100,

        // Sets the conditions for whether or not a request should attempt to retry.
        // Function signature should match: `function (\Exception $ex) : bool`.
        'restRetryFunction' => function (\Exception $e) {
            // Custom logic: ex. only retry if the error code is 404.
            return $e->getCode() === 404;
        },

        // Runs after the restRetryFunction. This might be used to simply consume the
        // exception and $arguments b/w retries. This returns the new $arguments thus allowing
        // modification on demand for $arguments. For ex: changing the headers in b/w retries.
        'restRetryListener' => function (\Exception $e, $retryAttempt, &$arguments) {
            // logic
        },
    ];
    foreach ($bucket->objects($operationRetriesOverrides) as $object) {
        printf('Object: %s' . PHP_EOL, $object->name());
    }
}

Python

Para modificar o comportamento de repetição predefinido, crie uma cópia do objeto google.cloud.storage.retry.DEFAULT_RETRY chamando-o com um método with_BEHAVIOR. A biblioteca cliente Python usa automaticamente estratégias de recuo para repetir pedidos se incluir o parâmetro DEFAULT_RETRY.

Tenha em atenção que with_predicate não é suportado para operações que obtenham ou enviem dados de payload para objetos, como carregamentos e transferências. Recomendamos que modifique os atributos um a um. Para mais informações, consulte a referência de repetição do google-api-core.

Para configurar a sua própria repetição condicional, crie um objeto ConditionalRetryPolicy e envolva o seu objeto Retry personalizado com DEFAULT_RETRY_IF_GENERATION_SPECIFIED, DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED ou DEFAULT_RETRY_IF_ETAG_IN_JSON.

Consulte o seguinte exemplo de código para saber como personalizar o comportamento de repetição.

from google.cloud import storage
from google.cloud.storage.retry import DEFAULT_RETRY


def configure_retries(bucket_name, blob_name):
    """Configures retries with customizations."""
    # The ID of your GCS bucket
    # bucket_name = "your-bucket-name"
    # The ID of your GCS object
    # blob_name = "your-object-name"

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(blob_name)

    # Customize retry with a timeout of 500 seconds (default=120 seconds).
    modified_retry = DEFAULT_RETRY.with_timeout(500.0)
    # Customize retry with an initial wait time of 1.5 (default=1.0).
    # Customize retry with a wait time multiplier per iteration of 1.2 (default=2.0).
    # Customize retry with a maximum wait time of 45.0 (default=60.0).
    modified_retry = modified_retry.with_delay(initial=1.5, multiplier=1.2, maximum=45.0)

    # blob.delete() uses DEFAULT_RETRY by default.
    # Pass in modified_retry to override the default retry behavior.
    print(
        f"The following library method is customized to be retried according to the following configurations: {modified_retry}"
    )

    blob.delete(retry=modified_retry)
    print(f"Blob {blob_name} deleted with a customized retry strategy.")

Ruby

Quando inicializa o cliente de armazenamento, todas as configurações de repetição são definidas para os valores apresentados na tabela acima. Para modificar o comportamento de repetição predefinido, transmita as configurações de repetição ao inicializar o cliente de armazenamento.

Para substituir o número de novas tentativas de uma operação específica, transmita retries no parâmetro options da operação.

def configure_retries bucket_name: nil, file_name: nil
  # The ID of your GCS bucket
  # bucket_name = "your-unique-bucket-name"

  # The ID of your GCS object
  # file_name = "your-file-name"

  require "google/cloud/storage"

  # Creates a client
  storage = Google::Cloud::Storage.new(

    # The maximum number of automatic retries attempted before returning
    # the error.
    #
    # Customize retry configuration with the maximum retry attempt of 5.
    retries: 5,

    # The total time in seconds that requests are allowed to keep being retried.
    # After max_elapsed_time, an error will be returned regardless of any
    # retry attempts made during this time period.
    #
    # Customize retry configuration with maximum elapsed time of 500 seconds.
    max_elapsed_time: 500,

    # The initial interval between the completion of failed requests, and the
    # initiation of the subsequent retrying request.
    #
    # Customize retry configuration with an initial interval of 1.5 seconds.
    base_interval: 1.5,

    # The maximum interval between requests. When this value is reached,
    # multiplier will no longer be used to increase the interval.
    #
    # Customize retry configuration with maximum interval of 45.0 seconds.
    max_interval: 45,

    # The multiplier by which to increase the interval between the completion
    # of failed requests, and the initiation of the subsequent retrying request.
    #
    # Customize retry configuration with an interval multiplier per iteration of 1.2.
    multiplier: 1.2
  )

  # Uses the retry configuration set during the client initialization above with 5 retries
  file = storage.service.get_file bucket_name, file_name

  # Maximum retry attempt can be overridden for each operation using options parameter.
  storage.service.delete_file bucket_name, file_name, options: { retries: 4 }
  puts "File #{file.name} deleted with a customized retry strategy."
end

APIs REST

Use o algoritmo de retirada exponencial para implementar a sua própria estratégia de repetição.

Algoritmo de retirada exponencial

Um algoritmo de retirada exponencial repete os pedidos com intervalos de tempo exponencialmente crescentes entre os pedidos, até um tempo de retirada máximo. Geralmente, deve usar a retirada exponencial com variação aleatória para tentar novamente os pedidos que cumprem os critérios de resposta e idempotência. Para ver as práticas recomendadas de implementação de novas tentativas automáticas com retirada exponencial, consulte o artigo Como resolver falhas em cascata.

Antipadrões de repetição

Recomendamos que use ou personalize os mecanismos de repetição incorporados, quando aplicável. Consulte o artigo sobre personalizar repetições. Quer esteja a usar os mecanismos de repetição predefinidos, a personalizá-los ou a implementar a sua própria lógica de repetição, é fundamental evitar os seguintes padrões de solução de problemas comuns, uma vez que podem agravar os problemas em vez de os resolver.

A tentar novamente sem retirada

Voltar a tentar pedidos imediatamente ou com atrasos muito curtos pode levar a falhas em cascata, que são falhas que podem acionar outras falhas.

Como evitar esta situação: implemente a retirada exponencial com variação. Esta estratégia aumenta progressivamente o tempo de espera entre novas tentativas e adiciona um elemento aleatório para evitar que as novas tentativas sobrecarreguem o serviço.

Voltar a tentar incondicionalmente operações não idempotentes

A execução repetida de operações que não são idempotentes pode levar a efeitos secundários não intencionais, como substituições ou eliminações não intencionais de dados.

Como evitar esta situação: compreenda detalhadamente as caraterísticas de idempotência de cada operação, conforme detalhado na secção Idempotência das operações. Para operações não idempotentes, certifique-se de que a lógica de repetição consegue processar potenciais duplicados ou evite repeti-las por completo. Tenha cuidado com as novas tentativas que podem levar a condições de concorrência.

Voltar a tentar erros que não podem ser repetidos

Tratar todos os erros como se fosse possível tentar novamente pode ser problemático. Alguns erros, por exemplo, falhas de autorização ou pedidos inválidos, são persistentes e a repetição dos mesmos sem resolver a causa subjacente não tem êxito e pode fazer com que as aplicações fiquem presas num ciclo infinito.

Como evitar esta situação: categorize os erros em temporários (repetíveis) e permanentes (não repetíveis). Volte a tentar apenas erros transitórios, como códigos HTTP 408, 429 e 5xx, ou problemas de ligação específicos. Para erros permanentes, registe-os e resolva a causa subjacente de forma adequada.

Ignorar limites de novas tentativas

As novas tentativas indefinidas podem levar à exaustão de recursos na sua aplicação ou enviar continuamente pedidos para um serviço que não vai recuperar sem intervenção.

Como evitar esta situação: personalize os limites de repetição de acordo com a natureza da sua carga de trabalho. Para cargas de trabalho sensíveis à latência, considere definir uma duração máxima total de novas tentativas para garantir uma resposta ou uma falha atempada. Para cargas de trabalho em lote, que podem tolerar períodos de repetição mais longos para erros transitórios do lado do servidor, pondere definir um limite de repetição total mais elevado.

Adicionar novas tentativas desnecessariamente

A adição de uma lógica de repetição ao nível da aplicação personalizada além dos mecanismos de repetição existentes pode levar a um número excessivo de tentativas de repetição. Por exemplo, se a sua aplicação tentar novamente uma operação três vezes e a biblioteca de cliente subjacente também a tentar novamente três vezes para cada uma das tentativas da sua aplicação, pode acabar com nove tentativas. O envio de um número elevado de novas tentativas para erros que não podem ser repetidos pode levar à limitação de pedidos, o que limita o débito de todas as cargas de trabalho. Um número elevado de novas tentativas também pode aumentar a latência dos pedidos sem melhorar a taxa de êxito.

Como evitar esta situação: recomendamos que use e configure os mecanismos de repetição incorporados. Se tiver de implementar novas tentativas ao nível da aplicação, como para uma lógica de negócio específica que abranja várias operações, faça-o com uma compreensão clara do comportamento de novas tentativas subjacente. Considere desativar ou limitar significativamente as novas tentativas numa das camadas para evitar efeitos multiplicativos.

O que se segue?