
# 使用指数退避方法对DEW服务请求错误进行重试
#### 应用场景
当您调用API时，收到返回的错误信息，可参照本文使用指数退避方法对请求错误进行重试。
![](https://support.huaweicloud.com/bestpractice-dew/public_sys-resources/notice_3.0-zh-cn.png)
对接KMS时，必须有重试，包括不限于504、502、500、429等错误码，且推荐重试3\~5次。针对502和504错误码，推荐超时时间5\~8秒。不建议配置过长超时时间，否则会造成客户侧无法响应。
#### 应用原理
当服务侧出现连续错误响应（如限流错误）时，持续的访问只会导致持续的发生冲突，使用指数退避方法，可以有效的规避该类错误。
#### 约束条件
当前账号下有用于加密的密钥，密钥"状态"为"启用"。
#### 指数退避代码示例
1. 请准备基础认证信息：
   - ACCESS_KEY：华为账号Access Key，获取方式请参见[获取AK/SK](https://support.huaweicloud.com/iam_faq/iam_01_0618.html)。
   
   - SECRET_ACCESS_KEY：华为账号Secret Access Key，获取方式请参见[获取AK/SK](https://support.huaweicloud.com/iam_faq/iam_01_0618.html)。
   
   - PROJECT_ID：局点项目ID，获取方式请参见[获取项目ID](https://support.huaweicloud.com/api-iam/iam_17_0002.html)。
   
   - KMS_ENDPOINT：华为云KMS服务访问终端地址，获取方式请参见[终端节点](https://support.huaweicloud.com/api-dew/dew_02_0052.html#section2)。
   
   - 认证用的ak和sk直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全。
   
   - 本示例以ak和sk保存在环境变量中来实现身份验证为例，运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
    
2. 指数退避代码
   ```
   import com.huaweicloud.sdk.core.auth.BasicCredentials;
    import com.huaweicloud.sdk.core.auth.ICredential;
    import com.huaweicloud.sdk.core.exception.ClientRequestException;
    import com.huaweicloud.sdk.kms.v2.model.EncryptDataRequest;
    import com.huaweicloud.sdk.kms.v2.model.EncryptDataRequestBody;
    import com.huaweicloud.sdk.kms.v2.KmsClient;
    public class KmsEncryptExample {
        
        private static final String ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_AK");
        private static final String SECRET_ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_SK");
        private static final String KMS_ENDPOINT = "xxxx";
        private static final String KEY_ID = "xxxx";
        private static final String PROJECT_ID = "xxxx";
        private static KmsClient KmsClientInit() {
            ICredential auth = new BasicCredentials()
                    .withAk(ACCESS_KEY)
                    .withSk(SECRET_ACCESS_KEY)
                    .withProjectId(PROJECT_ID);
            return KmsClient.newBuilder()
                    .withCredential(auth)
                    .withEndpoint(KMS_ENDPOINT)
                    .build();
        }
        public static long getWaitTime(int retryCount) {
            long initialDelay = 200L;
            return (long) (Math.pow(2, retryCount) * initialDelay);
        }
        public static void encryptData(KmsClient client, String plaintext) {
            EncryptDataRequest request = new EncryptDataRequest().withBody(
                    new EncryptDataRequestBody()
                            .withKeyId(KEY_ID)
                            .withPlainText(plaintext));
            client.encryptData(request);
        }
        public static void main(String[] args) {
            int maxRetryTimes = 6;
            String plaintext = "plaintext";
            String errorMsg = "The throttling threshold has been reached";
            KmsClient client = KmsClientInit();
            for (int i = 0; i < maxRetryTimes; i++) {
                try {
                    encryptData(client, plaintext);
                    return;
                } catch (ClientRequestException e) {
                    if (e.getErrorMsg().contains(errorMsg)) {
                        try {
                            Thread.sleep(getWaitTime(i));
                        } catch (InterruptedException ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                }
            }
        }
    }
   ```
   
 
