面试官问我:你的项目如何处理重复请求(并发请求)?.docxVIP

面试官问我:你的项目如何处理重复请求(并发请求)?.docx

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
面试官问我:你的项目如何处理反复恳求(并发恳求)? 对于一些用户恳求,在某些情况下是可能反复发送的,假如是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦反复了,可能会导致很严峻的后果,例如买卖的接口假如反复恳求可能会反复下单。 反复的场景有可能是: 黑客拦截了恳求,重放 前端/客户端由于某些缘由恳求反复发送了,或者用户在很短的时间内反复点击了。网关重发 …. 本文争辩的是假如在服务端优雅地统一处理这种情况,如何禁止用户反复点击等客户端操作不在本文的争辩范畴。 利用独一恳求编号去重 你可能会想到的是,只需恳求有独一的恳求编号,那么就能借用Redis做这个去重——只需这个独一恳求编号在redis存在,证明处理过,那么就认为是反复的 代码或许如下: ????String?KEY?=?REQ12343456788;//恳求独一编号 ????long?expireTime?=??1000;//?1000毫秒过期,1000ms内的反复恳求会认为反复 ????long?expireAt?=?System.currentTimeMillis()?+?expireTime; ????String?val?=?expireAt@?+?expireAt; ????//redis?key还存在的话要就认为恳求是反复的 ????Boolean?firstSet?=?stringRedisTemplate.execute((RedisCallback)?connection?-?connection.set(KEY.getBytes(),?val.getBytes(),?Expiration.milliseconds(expireTime),?RedisStringCommands.SetOption.SET_IF_ABSENT)); ????final?boolean?isConsiderDup; ????if?(firstSet?!=?null??firstSet)?{//?第一次访问 ????????isConsiderDup?=?false; ????}?else?{//?redis值已存在,认为是反复了 ????????isConsiderDup?=?true; ????} 业务参数去重 上面的方案能处理具备独一恳求编号的场景,例如每次写恳求之前都是服务端前往一个独一编号给客户端,客户端带着这个恳求号做恳求,服务端即可完成去重拦截。 但是,很多的场景下,恳求并不会带这样的独一编号!那么我们能否针对恳求的参数作为一个恳求的标识呢? 先考虑简约的场景,假设恳求参数只要一个字段reqParam,我们可以利用以下标识去推断这个恳求能否反复。用户ID:接口名:恳求参数 String?KEY?=?dedup:U=+userId?+?M=?+?method?+?P=?+?reqParam; 那么当同一个用户访问同一个接口,带着同样的reqParam过来,我们就能定位到他是反复的了。 但是问题是,我们的接口通常不是这么简约,以目前的主流,我们的参数通常是一个JSON。那么针对这种场景,我们怎样去重呢? 计算恳求参数的摘要作为参数标识 假设我们把恳求参数(JSON)按KEY做升序排序,排序后拼成一个字符串,作为KEY值呢?但这可能格外的长,所以我们可以考虑对这个字符串求一个MD5作为参数的摘要,以这个摘要去取代reqParam的位置。 String?KEY?=?dedup:U=+userId?+?M=?+?method?+?P=?+?reqParamMD5; 这样,恳求的独一标识就打上了! 注:MD5理论上可能会反复,但是去重通常是短时间窗口内的去重(例如一秒),一个短时间内同一个用户同样的接口能拼出不同的参数导致一样的MD5几乎是不行能的。 连续优化,考虑剔除部分时间因子 上面的问题其实已经是一个很不错的处理方案了,但是实际投入使用的时候可能发觉有些问题:某些恳求用户短时间内反复的点击了(例如1000毫秒发送了三次恳求),但绕过了上面的去重推断(不同的KEY值)。 缘由是这些恳求参数的字段里面,是带时间字段的,这个字段标记用户恳求的时间,服务端可以借此丢弃掉一些老的恳求(例如5秒前)。如下面的例子,恳求的其他参数是一样的,除了恳求时间相差了一秒: ????//两个恳求一样,但是恳求时间差一秒 ????String?req?=?{\n?+ ????????????\requestTime\?:\20210101120001\,\n?+ ????????????\requestValue\?:\1000\,\n?+ ????????????\requestKey\?:\key\\n?+ ????????????}; ????String?req2?=

文档评论(0)

bob157641554 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档