有奖捉虫:行业应用 & 管理与支持文档专题 HOT
文档中心 > 密钥管理系统 > 最佳实践 > 指数回退策略应对服务限频

异常处理的策略建议

请求 KMS API 接口,即应用程序的请求发送到 KMS 远程服务器时,若出现异常报错,建议您可以采用以下策略进行处理:
取消:当返回错误显示故障是非暂时性,或重新执行后也无法成功,则应当终止/取消程序调用并报告异常。
重试:当返回错误是不常见或比较少见,如网络包在传输过程中损坏,但被发送,这种情况下可以立即采取重试。
延迟重试:当返回错误是普通的连接或繁忙相关导致,则服务可能需要短时间的恢复,从而清除堆积的工作等,此类问题,等待一个合适时间后进行重试。
本文以延迟重试的策略展开说明,上述提到的等待时间(即延迟时间),可以采取逐步增加方式,或使用定时策略(如指数回退)来实现。因为调用 KMS API 接口服务会限制频率,所以当您调用的并发过高时,可以采用延迟重试的方法来避免限频所带来的问题。

指数回退

伪代码

//使用逐步增加的方式来延迟重试某个操作
InitDelayValue = 100
For(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 base64
import math
import time
import os
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.kms.v20190118 import kms_client, models


def 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 None

def BackoffFunction(RetryCount):
InitDelayValue = 100
DelayTime = math.pow(2, RetryCount) * InitDelayValue
return DelayTime

if __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
注意
如需解决其他特定的错误,您可以直接对 except 语句的内容做更改、调整即可。
根据自己的代码逻辑、业务策略等,进行定时策略的规划与制定,从而设置最优的初始延迟值(InitDelayValue)及重试次数(Retries),避免阈值设置过低或过高,影响整体业务运转。