Ao chamar APIs do KMS, erros podem ocorrer ocasionalmente. Este tópico descreve como usar o backoff exponencial para repetir solicitações com erro.
Contexto
Erros podem surgir durante a chamada de uma API de service. Nessas situações, repita a solicitação na aplicação.
Alguns SDKs da Alibaba Cloud suportam repetições automáticas por meio de configuração. O Alibaba Cloud SDK for .NET, por exemplo, permite configurar políticas de repetição. Quando as repetições automáticas não se aplicarem, use o método descrito neste tópico.
Estratégias de repetição
Se uma solicitação falhar devido a um erro de servidor (5xx) ou a um erro de limitação de taxa, repita-a usando as seguintes estratégias:
-
Repetição simples.
Por exemplo, repita uma vez por segundo durante 10 segundos.
-
Backoff exponencial.
Para respostas de erro consecutivas, o intervalo de espera entre tentativas aumenta progressivamente. Respeite o intervalo máximo de atraso e o número máximo de tentativas. O backoff exponencial evita conflitos contínuos durante as repetições. Por exemplo, quando as solicitações excedem a cota de limitação em um curto período, essa estratégia previne eficazmente erros persistentes de throttling.
Os gateways dedicados do KMS não impõem limite superior ao número de chamadas de API. Em vez disso, adotam uma abordagem de melhor esforço para maximizar o uso dos recursos de computação e armazenamento da instância no processamento das solicitações. Portanto, erros de limitação de taxa não ocorrem.
Pseudocódigo para backoff exponencial
O pseudocódigo a seguir demonstra como repetir uma operação com atrasos incrementais.
initialDelay = 200
retries = 0
DO
wait for (2^retries * initialDelay) milliseconds
status = CallSomeAPI()
IF status == SUCCESS
retry = false // Succeeded, stop calling the API again.
ELSE IF status = THROTTLED || status == SERVER_NOT_READY
retry = true // Failed because of throttling or server busy, try again.
ELSE
retry = false // Some other error occurred, stop calling the API again.
END IF
retries = retries + 1
WHILE (retry AND (retries < MAX_RETRIES))
Use backoff exponencial para lidar com limitação de taxa do KMS
O exemplo Java a seguir ilustra o uso de backoff exponencial para tratar erros de limitação de taxa quando o KMS executa a operação Decrypt.
Faça modificações simples para repetir tipos específicos de erros de servidor, como HTTP 503.
Estime a quantidade de solicitações enviadas pelo cliente em um período específico e ajuste o atraso inicial (
initialDelay) e o número de repetições (maxRetries).
Um par de AccessKey de uma conta Alibaba Cloud tem permissões para todas as operações de API. Recomendamos usar um usuário RAM para chamar operações de API ou executar tarefas rotineiras de O&M. Para evitar riscos de segurança, não codifique seu AccessKey ID e AccessKey Secret diretamente no código do projeto. Credenciais codificadas podem resultar em vazamentos que comprometem todos os resources da sua conta.
Este tópico fornece um exemplo de como configurar as variáveis de ambiente ALIBABA_CLOUD_ACCESS_KEY_ID e ALIBABA_CLOUD_ACCESS_KEY_SECRET para autenticação de identidade.
Para mais informações sobre como configurar credenciais de acesso, consulte Manage access credentials.
O método para configurar variáveis de ambiente varia conforme o sistema operacional. Para mais detalhes, consulte Configure environment variables on Linux, macOS, and Windows.
import com.aliyun.kms20160120.Client;
import com.aliyun.kms20160120.models.DecryptRequest;
import com.aliyun.kms20160120.models.DecryptResponse;
import com.aliyun.tea.*;
import com.aliyun.teautil.models.RuntimeOptions;
import java.nio.charset.StandardCharsets;
public class Main {
private static Client kmsClient;
private static Client kmsClient(String regionId, String accessKeyId, String accessKeySecret) throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
.setAccessKeyId(accessKeyId)
.setAccessKeySecret(accessKeySecret);
config.setRegionId(regionId) ;
return new Client(config);
}
private static String kmsDecrypt(String cipherTextBlob) throws Exception {
DecryptRequest decryptRequest = new DecryptRequest()
// Specify the ciphertext that you want to decrypt.
.setCiphertextBlob(cipherTextBlob);
DecryptResponse response = kmsClient.decryptWithOptions(decryptRequest, new RuntimeOptions());
// Obtain the decrypted plaintext from the response.
String plaintext = response.getBody().getPlaintext();
System.out.println("Ciphertext (Base64): " + cipherTextBlob);
System.out.println("Decrypted Plaintext: " + plaintext);
return plaintext;
}
public static long getWaitTimeExponential(int retryCount) {
final long initialDelay = 200L;
long waitTime = ((long) Math.pow(2, retryCount) * initialDelay);
return waitTime;
}
public static void main(String[] args) throws Exception {
String regionId = "<region ID>"; // Example: "cn-shanghai"
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
String cipherTextBlob ="a2V5LXNoaDY4M**********w=";
int maxRetries = 5;
kmsClient = kmsClient(regionId, accessKeyId, accessKeySecret);
for (int i = 0; i < maxRetries; i++) {
try {
String plainText = kmsDecrypt(cipherTextBlob);
return;
} catch (Exception e) {
e.printStackTrace();
if (e.getMessage().contains("Rejected.Throttling")) { // Throttled. Retry the request.
try {
Thread.sleep(getWaitTimeExponential(i + 1));
} catch (InterruptedException ignore) {
}
} else {
break; // Not a throttling error. Stop retrying.
}
}
}
}
}