dedecms 网站还原教程,seo培训班 有用吗,腾讯云备案网站名称,室内设计联盟app下载为什么要做重复请求的过滤呢#xff1f;不过滤不行吗#xff1f;过滤重复请求很难吗#xff1f;加一个请求ID不就好了吗#xff1f;每个技术难点的话题#xff0c;肯定是由一个产品需求引发的#xff0c;俗话说#xff1a;如果没有产品经理#xff0c;程序员将不需要听… 为什么要做重复请求的过滤呢不过滤不行吗过滤重复请求很难吗加一个请求ID不就好了吗每个技术难点的话题肯定是由一个产品需求引发的俗话说如果没有产品经理程序员将不需要听诊器但是会失业产生背景重复请求能够对系统造成伤害是架构中很难避免的一个设计问题一般情况下读请求很少会造成致命性的故障主要是系统的写请求很多时候一个重复写的动作会是我们程序员加班的缘由。比如用户使用积分兑换物品重复的请求会造成用户积分的重复扣减而作为线上系统如果日志等辅助打的不好的话排查原因其实需要很多时间。一般的产品经理设计系统的时候并不会涉及到这类异常情况但是一旦出现问题产品经理就会找到程序员骂娘多么悲哀的故事人家付出5分精力设计的系统我们却要花费10分的精力去编码和维护。重复的业务请求有的时候对系统造成的影响很大所以程序员在设计的时候尤其要注意产生的原因有很多黑客进行了拦截人为的重放了请求客户端因为某些原因用户在很短的时间内重放了请求一些中间件比如网关重放了请求未知的其他情况道理很简单用一张图表达的会更清爽一些image抽象出来是不是很简单但是落地却并非像这张图一样简单从这张图上一眼就可以看到整个过程的重点难点在于过滤器这个逻辑设计部分这部分可以和业务代码融合在一起有的时候也可以相分离比如有的网关可以内嵌脚本比如lua就完全可以做到和业务无关但是通常情况下落地的代码却和业务息息相关。客户端处理客户端处理重复请求是一种可以有效过滤正常请求的手段为什么这么说呢当一个用户正常操作的时候客户端完全可以利用loading的方式或者其他过滤重复手段来达到目的比如当用户点击一个按钮的时候弹出loading窗口方式用户再次操作。再比如客户端可以设置一个类似于布隆过滤的数据结构配合对应的过滤算法也可以达到过滤重复请求的效果。不过客户端的任何解决方案也只是治标不治本毕竟客户端在整个系统架构中是最不可靠的终端。请求标识重复请求过滤的关键在于过滤器的逻辑设计目前最常用落地最多当属使用请求ID的方式。大体流程如下客户端发送请求的时候会生成随机的请求ID随着业务参数一起传送到服务端服务端会根据传送上来的请求ID做是否重复的判断服务器的判断逻辑其实有很多落地方案了比如最常见的利用redis来存储请求ID以下是伪代码(NetCore)public class Para
{public string ReqId{get ;set ;} //其他业务参数
}public bool IsExsit(Para p)
{//利用redis来判断当前的key是否存在bool isExsitredisMethond(p.ReqId);//如果存在则说明是重复请求,如果不存在说明不是重复请求并且添加到redisif(!isExsit){AddRedis(p.ReqId);}return isExsit;}
一般网上的文章都到此为止了这种方案有没有问题呢答案有问题1正常的客户端重复请求一般情况下真的会根据我们写的代码过滤掉重复请求为什么说一般情况呢那是因为分布式的原因极限情况下也会导致重复的请求到业务处理端比如以下情况请求被路由到了A服务器A服务器会去请求Redis判断是否有相同的请求ID存在如果是第一次请求Redis会返回不存在同样的时间客户端或者黑客重放了同样的请求这个请求被路由到了B服务器B服务器同样会请求Redis来判断是否存在这个时候由于A服务器还没回写Redis所以B服务器得到的结果也是不存在该请求这样就导致了业务端收到了两次同样的请求会导致业务不可预期的结果可见一个小小重复过滤请求可能还需要分布式锁的出场才可以问题2即便请求中加了唯一的请求ID但是这个ID并没有安全保证或者说这个ID是可以篡改的。当黑客拦截到请求随便改一下请求ID在重放就搞定你了。所以加的请求ID还需要一个安全机制来保证安全不然这个参数其实意义不大。业务签名由于单纯添加请求ID并不能解决问题所以我们需要一种保证请求ID的机制目前来看普遍的落地方案是根据业务参数生成摘要也就是所谓的加签操作。加签操作可以有效的防止参数被篡改。如果你做过微信相关的开发你会发现和微信服务器的交互也是基于加签操作的。而生成的签名可以作为请求ID以下是伪代码 //客户端生成签名string sighMD5($参数1值1参数2值2time当前时间戳)
以上只是例子虽然MD5算法有产生重复数据的可能性但是对于当前这个业务场景来说足够了。细心的同学会发现参数当中加了一个时间戳的参数这个是我故意加的这个时间戳在这个场景下会出现问题什么问题呢时间戳问题当前的请求场景是要过滤重复的请求什么样的请求算是重复请求呢关键是这个定义要明确我看了很多重复过滤请求的文章重复请求这个概念其实定义的不好这个是和具体业务场景相关的。举个栗子当用户一秒内重复点击某个按钮算是重复请求那10秒内重复点击呢用户一秒之内对同一个商品下单算重复请求那10秒内呢这个定义就涉及到了上面所说的时间戳参数的问题时间戳是否要参与生成签名要根据具体的业务场景来定义不过我还是要建议请求的参数中带上时间戳无论它参不参与签名至于为什么这么做当时间长了你就知道了写在最后过滤重复请求这个需求并没有像想象中那么容易并非只要加上一个请求ID就完事了它涉及到安全以及分布式的问题在某些场景下比如秒杀还会涉及到性能以及高可用等非功能性问题所以那些说只需要一个请求ID就能过滤的同学请不要再误导别人了技术是神圣不可侵犯的。还是那句话具体的业务影响到具体的代码实现脱离业务讲架构其实就是耍流氓