异常处理的策略建议
请求 KMS API 接口,即应用程序的请求发送到 KMS 远程服务器时,若出现异常报错,建议您可以采用以下策略进行处理:
取消:当返回错误显示故障是非暂时性,或重新执行后也无法成功,则应当终止/取消程序调用并报告异常。
重试:当返回错误是不常见或比较少见,如网络包在传输过程中损坏,但被发送,这种情况下可以立即采取重试。
延迟重试:当返回错误是普通的连接或繁忙相关导致,则服务可能需要短时间的恢复,从而清除堆积的工作等,此类问题,等待一个合适时间后进行重试。
本文以延迟重试的策略展开说明,上述提到的等待时间(即延迟时间),可以采取逐步增加方式,或使用定时策略(如指数回退)来实现。因为调用 KMS API 接口服务会限制频率,所以当您调用的并发过高时,可以采用延迟重试的方法来避免限频所带来的问题。
指数回退
伪代码
//使用逐步增加的方式来延迟重试某个操作InitDelayValue = 100For(Retries = 0; Retries < MAX_RETRIES; Retries = Retries+1)wait for (2^Retries * InitDelayValue) millisecondsStatus = KmsApiRequest()IF Status == SUCCESSBREAK // Succeeded, stop calling the API again.ELSE IF Status = THROTTLED || Status == SERVER_NOT_READYCONTINUE // Failed due to throttling or server busy, try again.ELSEBREAK // 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 clientexcept TencentCloudSDKException as err:print(err)return Nonedef BackoffFunction(RetryCount):InitDelayValue = 100DelayTime = math.pow(2, RetryCount) * InitDelayValuereturn DelayTimeif __name__ == '__main__':# 用户自定义参数secretId = os.getenv('SECRET_ID') # read from environment variable or use whitebox encryption to protect secret IDsecretKey = 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 = 0MaxRetries = 10client = KmsInit(region, secretId, secretKey)req = models.EncryptRequest()req.KeyId = keyIdreq.Plaintext = base64.b64encode(plaintext)while Retries < MaxRetries:try:Retries += 1rsp = client.Encrypt(req) # 调用加密接口print 'plaintext: ',plaintext,'CiphertextBlob: ',rsp.CiphertextBlobbreakexcept TencentCloudSDKException as err:if err.code == 'InternalError' or err.code == 'RequestLimitExceeded':if Retries == MaxRetries:breaktime.sleep(BackoffFunction(Retries + 1))continueelse:print(err)breakexcept Exception as err:print(err)break
注意:
如需解决其他特定的错误,您可以直接对 except 语句的内容做更改、调整即可。
根据自己的代码逻辑、业务策略等,进行定时策略的规划与制定,从而设置最优的初始延迟值(InitDelayValue)及重试次数(Retries),避免阈值设置过低或过高,影响整体业务运转。