前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >腾讯云 API 最佳实践: 善用幂等性

腾讯云 API 最佳实践: 善用幂等性

原创
作者头像
zqfan
修改2021-08-11 22:49:29
6.8K4
修改2021-08-11 22:49:29
举报
文章被收录于专栏:腾讯云API腾讯云API

有些开发者问我云服务器“创建实例”接口有一个参数“ClientToken”不知道有什么作用。本文作一个简单的解答。

  1. ClientToken 是防止重复创建资源的;
  2. 对于创建资源的接口,你总是应该用到 ClientToken;
  3. 不同的请求用不同的 ClientToken,同一个请求用相同的 ClientToken;
  4. 欢迎对不支持 ClientToken 的发货类接口提出支持的诉求。

注意这里的同一个请求不是说你参数相同就是同一个请求,而是指你的目的性。举例来说,zqfan这个用户现在创建了一台服务器,过会儿又想创建同样的一台服务器,这叫两个不同的请求。虽然参数一样,但目的就是创建规格一样的两台机器,分两次请求发送,这两个请求的 ClientToken 应该指定不同的值。

ClientToken是什么?

如文档所言:

“用于保证请求幂等性的字符串。该字符串由客户生成,需保证不同请求之间唯一,最大值不超过64个ASCII字符。若不指定该参数,则无法保证请求的幂等性。”

ClientToken是需要调用者指定的,通常你直接给一个 UUID就够了 ,例如 a9a90aa6-751a-41b6-aad6-fae360632808 。更好一点的,你可以指定一个前缀以示用途,例如CT-a9a90aa6-751a-41b6-aad6-fae360632808 。

什么是幂等性?

wikipedia上的解释说:

“Idempotence is the property of certain operations in mathematics and computer science that they can be applied multiple times without changing the result beyond the initial application.”

简单地说就是无论操作多少次,结果都应该是一样的。用数学语言来表述: x * x = x

为什么要幂等性?

在查询类的接口里,你基本上是不会想要上一次的结果,而只关心当前的结果,在你不做改变系统状态的操作时,你反复调用查询接口,其返回应该是一样的。同样的,修改操作你也不会关心上一次结果,当你重复调用修改操作时,只要这一次成功了,目的就算达到了,如果失败了,再重试(如果可重试的话)直到成功即可。删除操作同理。

但是对于一些资源创建类的,单纯的重试就有问题了。云服务器的“创建实例”接口可以一次创建一百台实例,包年包月预付费。如果这一次你调用接口失败了,例如在返回结果前网络中断了,死机了,你设置的超时时间太短提前关闭了连接等等,服务器当前的状态你是不知道的。你只能去查询实例列表,还得按时间排序,确定下到底是否创建成功了,哪一批是上一次请求创建的,最终的结果难以保证正确性。如果是在代码里呢,你该怎么办?到底是重试,还是放弃直接抛出异常?重试,你会立刻创建新的一百台实例。抛出异常,可能服务器明明成功了,只是因为你所在环境网络不稳定,你的程序就运行不下去了,你的代码健壮性就太差了。

为了防止创建资源时发生重复下单的问题,引入幂等性的概念。服务器根据唯一标识符, 在腾讯云 API 中是 ClientToken ,判断操作是否曾经发生过。如果找到了同样的标识符,则表示这个操作发生过,直接返回上一次的结果;如果没有发生过,继续执行。

例如,现在你调用“创建实例”接口,同时指定了 ClientToken=CT-a9a90aa6-751a-41b6-aad6-fae360632808 。假设接口发生异常,你立刻再次发送同样的请求,带上同样的 ClientToken ,服务器会返回上一次的结果,而不是再去创建一批新的实例。

幂等性的局限性?

严格的幂等是理想的结果,实际上,现实的系统是难以达到的。古希腊哲学家赫拉克利特说过:"人不能两次踏进同一条河流"。

例如云服务器有一个接口“查看实例列表”,它是个只读的接口,返回的实例里有个实例状态的属性,按理它应该是要幂等的,但是当你对其中某个云服务器关机后,又或者单纯的是服务器正在例行维护自动关机了,那下次再去调用返回的结果,显然和上一次会不一样的。何况每一个请求都有 RequestId 标识符,这个标识符每次都不一样以区别不同的请求。

再比如云服务器的另一个接口“退还实例”,如果退还成功,它会正常返回。当你再次退还,会返回资源未找到的错误信息。这种情况下,虽然返回的不同,但是你的目的达到了。正常删除资源和试图删除不存在的资源,它们表义不同,但实际结果是等价的,都达到了令目标资源不再存在的目的。

又如前文所述,幂等性需要记录每一个带有幂等操作标识符的请求的结果。服务器无意承担一些不必要的存储负担,因此不涉及到资源变动的只读接口,或者涉及到资源变动,但是本身就自带幂等属性的修改、删除接口都是不会有幂等操作标识符的。

我们还需要考虑高并发的场景。假设两个请求同时发起,都有同样的 ClientToken ,那么总有一个返回先后,后返回的理论上是要和先返回的一致的。但是在分布式高并发系统里,先发出的请求未必先到达服务器,先到达服务器的未必先入库。如果先入库的请求还未处理完毕,另一个请求无法入库(唯一性)又查询不到结果,只能返回一个内部异常(理想情况下应该返回操作正在执行中)。在调用者看来,可能会发生第一个返回是内部异常,第二个返回是正常的预期结果的情况。严格来说,这并不是幂等的,但是只要调用者合理安排,这种情况是可以避免的,例如失败请求后你可以休眠几十毫秒到几秒再去请求。只要某一次请求有确定的结果,后续重复的请求都将返回这个结果。

调用者使用幂等性时,需要注意,不同的请求,它的 ClientToken 必须是不一样的,同一个请求,它的 ClientToken 必须是一样的。也就是说,服务器端完全依靠 ClientToken 来判断是否是同一个请求,而不管其他具体的参数。这就要求调用者得自己确保 ClientToken 不冲突,否则你以为接口返回成功了,其实是之前某一个请求的结果 。此外,为了将来能重复查询,你还必须将其缓存或者持久化。

腾讯云对幂等性支持的情况?

原则上,我们要求所有的资源创建类接口都要支持幂等性。但是每个产品的情况是各有差异的,我们暂时无法一刀切,只能根据实际情况进行判断。有些产品可能刚开始觉得没必要支持幂等性,但是后来随着用户的诉求,或者产品自身的发展,才决定要支持幂等性。这是一个发展的过程,还请用户谅解,并对我们产品的 API 监督和督促,提出意见和建议,共同成长,创造价值。

以下是目前(2021-08-11)我掌握的,支持幂等性的 API 3.0 接口:

总结

看完了这篇短文,你明白了 ClientToken 的作用了吗?这里再回顾一下你在使用腾讯云 API 时应当采取的策略:

  1. ClientToken 是防止重复创建资源的;
  2. 对于创建资源的接口,你总是应该用到 ClientToken;
  3. 不同的请求用不同的 ClientToken,同一个请求用相同的 ClientToken;
  4. 欢迎对不支持 ClientToken 的创建类接口提出诉求。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ClientToken是什么?
  • 什么是幂等性?
  • 为什么要幂等性?
  • 幂等性的局限性?
  • 腾讯云对幂等性支持的情况?
  • 总结
相关产品与服务
云 API
云 API 是腾讯云开放生态的基石。通过云 API,只需少量的代码即可快速操作云产品;在熟练的情况下,使用云 API 完成一些频繁调用的功能可以极大提高效率;除此之外,通过 API 可以组合功能,实现更高级的功能,易于自动化, 易于远程调用, 兼容性强,对系统要求低。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档