一、异常处理的策略建议
·取消:当返回错误显示故障是非暂时性,或重新执行后也无法成功,则应当终止/取消程序调用并报告异常。
·重试:当返回错误是不常见或比较少见,如网络包在传输过程中损坏,但被发送,这种情况下可以立即采取重试。
·延迟重试:当返回错误是普通的连接或繁忙相关导致,则服务可能需要短时间的恢复,从而清除堆积的工作等,此类问题,等待一个合适时间后进行重试。
这篇以延迟重试的策略展开说明,上述提到的等待时间(即延迟时间),可以采取逐步增加方式,或使用定时策略(如指数回退)来实现。因为调用 KMS API 接口服务会限制频率,所以当你调用的并发过高时,可以采用延迟重试的方法来避免限频所带来的问题。
二、伪代码
//使用逐步增加的方式来延迟重试某个操作InitDelayValue = 100For(Retries = 0; Retries < MAX_RETRIES; Retries = Retries+1) wait for (2^Retries * InitDelayValue) milliseconds Status = KmsApiRequest() IF Status == SUCCESS BREAK // Succeeded, stop calling the API again. ELSE IF Status == THROTTLED || Status == SERVER_NOT_READY CONTINUE // Failed due to throttling or server busy, try again. ELSE BREAK // another error occurs, stop calling the API again. END IF
三、策略运用
Python 示例:调用 KMS Encrypt 接口遇到限频错误时,如何使用指数回退方法处理。
# -*- coding: utf-8 -*-import base64import mathimport timeimport osfrom tencentcloud.common import credentialfrom tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKExceptionfrom tencentcloud.common.profile.client_profile import ClientProfilefrom tencentcloud.common.profile.http_profile import HttpProfilefrom tencentcloud.kms.v20190118 import kms_client, modelsdef KmsInit(region="ap-guangzhou", secretId="", secretKey=""): try: credProfile = credential.Credential(secretId, secretKey) client = kms_client.KmsClient(credProfile, region) return client except TencentCloudSDKException as err: print(err) return Nonedef BackoffFunction(RetryCount): InitDelayValue = 100 DelayTime = math.pow(2, RetryCount) * InitDelayValue return DelayTimeif __name__ == '__main__': # 用户自定义参数 secretId = os.getenv('SECRET_ID') # read from environment variable or use whitebox encryption to protect secret ID secretKey = os.getenv('SECRET_KEY') # read from environment variable or use whitebox encryption to protect secret key region = "ap-guangzhou" region = "ap-guangzhou" keyId = "replace-with-realkeyid" plaintext = "abcdefg123456789abcdefg123456789abcdefg" Retries = 0 MaxRetries = 10 client = KmsInit(region, secretId, secretKey) req = models.EncryptRequest() req.KeyId = keyId req.Plaintext = base64.b64encode(plaintext) while Retries < MaxRetries: try: Retries += 1 rsp = client.Encrypt(req) # 调用加密接口 print 'plaintext: ',plaintext,'CiphertextBlob: ',rsp.CiphertextBlob break except TencentCloudSDKException as err: if err.code == 'InternalError' or err.code == 'RequestLimitExceeded': if Retries == MaxRetries: break time.sleep(BackoffFunction(Retries + 1)) continue else: print(err) break except Exception as err: print(err) break