WebApi接口在超短时间内重复提交的解决方案

        刚刚,发生了一个件不可思议的事情,前端竟然可以在毫秒级的时间间隔,向同一个接口提交了两次请求,因为这里涉及到线程,两次请求产生的日志都是交叉在一起,一开始很难分析出来。

        目前还未找到重复请求的根源,估计和浏览器响应有关。前端已经做了防重复提交的代码,依然没拦住,就是请求时候第一时间出现遮罩,防止第二次点击,好像选择性失效了。那么就在后端做拦截吧。

        后端拦截需要有一个前提,就是必须是带token的请求,我总不可能让每个人都等待别人完成再来!假设把短时间的请求设置为1秒,就是1秒内,同一个用户不允许重复请求一个接口。在系统中,内置了一个Session对象,这个对象不是http请求中的session,是框架封装的一个用户缓冲容器,其本质是扩展的kv容器,例如static Dictionry Session;这里细节不说。有了这个容器就好办了,可以参考

.net中利用线程锁实现缓存自动超时_autoresetevent线程间同步时间太长_kaka9的博客-CSDN博客

当进入方法的时候,

//这里做一下改进

lock(Session) //这里要锁住Session对象,防止多线程抢占资源导致出错。

{

        if(Session.TryGetValue(methodKey,out DateTime lastdt)

        {

                //其实这里不用管取出来的数据是什么,都直接返回就可以了,毕竟缓存已经有这个数据了

                //也可以把lastdt这个最后调用的时间写到日志

               logHelper.Warn($"出现短时间内重复请求{methodKey});

                return true;

        }

        //设置超时时间1秒.

        Session.Set(methodKey,DateTime.Now,DateTimeOffset.Now.AddSeconds(1));

}

超过设定时间,methodKey将自动从Session移除,注意这里用的是DateTimeOffset,是绝对超时,不管中间methodKey被使用了多少次,到点就移除掉;如果是使用TimeSpan,则会顺延移除,就是使用一次,倒计时时间又重置为1秒。

好了,问题就这么愉快的解决了。

其实可以做的更好一点,就是使用Aop,把上述代码封装到一个标签上,程序员就可以节约大量的时间了,也方便后续维护,同时还可以设置标签当遇到重复调用的时候,是返回正确的状态还是报错状态,灵活度就大了很多。

再次提出一个问题,如果允许两次或者三次,或者设置次数限制,那么也是可以的,修改为Session.Inc(methodKey);

//todo

//当方法执行完成后,

var cnt = Session.Dec(methodKey);

这里就和超时没有什么关系了,当Dec后的cnt变量是0的时候,就是完成所有的调用了。其实这种情况很好出现,起码我是没有遇到过。只是顺带提一下。

你可能感兴趣的:(c#)