简单实现接口幂等性,根据参数的hascode实现:


  1.  参数介绍
    1.  WaitMillisecond : 请求等待毫秒数  
    2. CacheMillisecond:请求结果缓存毫秒数
  2. 参数具体使用场景  
    1. WaitMillisecond :用户频繁发起多次请求,只处理第一次请求,后续请求在这个等待(时间范围内)的均返回“正在执行..”,超出这个预设时间会再次真实请求到后台业务逻辑
    2. CacheMillisecond:第一次请求成功并且拿到结果,用户频繁发起请求 在这个缓存时间在,将返回上次一样的结果。直至过期

1.使用方式

        [HttpPost]
[HttpIdempotent(WaitMillisecond = 10000,CacheMillisecond = 3000)]
public async Task<IActionResult> Order(string orderNo)
     {
        //TODO
     }

2.具体实现

  1     /// <summary>
2 /// api request idempotence
3 /// </summary>
4 public class HttpIdempotentAttribute : Attribute, IAsyncResourceFilter
5 {
6
7 static HttpIdempotentAttribute()
8 {
9 var thread = new Thread(() =>
10 {
11 while (true)
12 {
13 var hashtableDatas = HashTable.Where(x => DateTime.Now > x.Value.Time).ToList();
14
15 if (hashtableDatas.Any())
16 {
17 foreach (var hashtableData in hashtableDatas)
18 {
19 HashTable.Remove(hashtableData.Key);
20 }
21 }
22 else
23 {
24 System.Threading.Thread.Sleep(2000);
25 }
26 }
27
28 });
29
30 thread.IsBackground = true;
31 thread.Start();
32 }
33
34 /// <summary>
35 /// http request parameter code collect
36 /// </summary>
37 private static readonly Dictionary<int, HashtableData> HashTable = new();
38
39 /// <summary>
40 /// http request parameter code
41 /// </summary>
42 public int _httpHasCode;
43
44 /// <summary>
45 /// waiting for the last request , default value:1000
46 /// </summary>
47 public double WaitMillisecond { get; set; } = 1000;
48
49 /// <summary>
50 /// result cache Millisecond , default value:1000
51 /// </summary>
52 public double CacheMillisecond { get; set; } = 1000;
53
54 /// <summary>
55 /// interceptor
56 /// </summary>
57 /// <param name="context"></param>
58 /// <param name="next"></param>
59 /// <returns></returns>
60 public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
61 {
62 await this.SetHttpParameterHasCode(context.HttpContext);
63
64 if (HashTable.ContainsKey(_httpHasCode))
65 {
66 var hashtableData = (HashtableData)HashTable[_httpHasCode];
67 if (hashtableData != null)
68 {
69 if (DateTime.Now < hashtableData.Time)
70 {
71 context.Result = hashtableData.Value;
72 return;
73 }
74 else if (DateTime.Now > hashtableData.Time)
75 {
76 HashTable.Remove(_httpHasCode);
77 }
78 else if (hashtableData.Value.Value == null)
79 {
80 context.Result = new ContentResult()
81 {
82 Content = "正在执行..."
83 };
84 return;
85 }
86 }
87 }
88
89 HashTable.Add(_httpHasCode, new HashtableData(DateTime.Now.AddMilliseconds(WaitMillisecond), null));
90
91 try
92 {
93 var netResult = await next();
94
95 if (HashTable.ContainsKey(_httpHasCode))
96 {
97 var hashtableData = (HashtableData)HashTable[_httpHasCode];
98 if (hashtableData != null)
99 {
100 hashtableData.Value = (ObjectResult)netResult.Result;
101 hashtableData.Time = DateTime.Now.AddMilliseconds(CacheMillisecond);
102 }
103 }
104 }
105 catch (Exception ex)
106 {
107 HashTable.Remove(_httpHasCode);
108 }
109
110 }
111
112 /// <summary>
113 /// get http request parameter code
114 /// </summary>
115 /// <returns></returns>
116 private async Task SetHttpParameterHasCode(HttpContext httpContext)
117 {
118
119 object readFromJson = null;
120
121 try
122 {
123 if (httpContext.Request.Method != "GET")
124 {
125 readFromJson = await httpContext.Request.ReadFromJsonAsync<object>();
126 }
127 }
128 catch (Exception e)
129 {
130 Console.WriteLine(e);
131 }
132
133 //todo 根据实际项目情况处理,获取Headers toke
134 var authorization = httpContext.Request.Headers["Authorization"];
135
136 var queryString = httpContext.Request.QueryString;
137 var bodyString = readFromJson == null ? string.Empty : readFromJson.ToString();
138
139 var builder = $"{authorization}-{queryString}-{bodyString}";
140
141 this._httpHasCode = builder.GetHashCode();
142 }
143
144 /// <summary>
145 /// Hashtable parameter model
146 /// </summary>
147 private class HashtableData
148 {
149 public HashtableData(DateTime time, ObjectResult value)
150 {
151 Time = time;
152 Value = value;
153 }
154 public DateTime Time { get; set; }
155 public ObjectResult Value { get; set; }
156 }
157 }

.net core api 请求实现接口幂等性的更多相关文章

  1. 防盗链&CSRF&API接口幂等性设计

    防盗链技术 CSRF(模拟请求) 分析防止伪造Token请求攻击 互联网API接口幂等性设计 忘记密码漏洞分析 1.Http请求防盗链 什么是防盗链 比如A网站有一张图片,被B网站直接通过img标签属 ...

  2. Spring中统一相同版本的api请求路径的一些思考

    Spring中统一相同版本的api请求路径的一些思考 问题场景 当我们在实际开发中,可能会遇到开发相同同版本的api, 假设相同版本的api请求路径为/v1/functionA,/v1/functio ...

  3. asp.net core mvc基于Redis实现分布式锁,C# WebApi接口防止高并发重复请求,分布式锁的接口幂等性实现

    使用背景:在使用app或者pc网页时,可能由于网络原因,api接口可能被前端调用一个接口重复2次的情况,但是请求内容是一样的.这样在同一个短暂的时间内,就会有两个相同请求,而程序只希望处理第一个请求, ...

  4. API接口幂等性框架设计

    表单重复提价问题 rpc远程调用时候 发生网络延迟  可能有重试机制 MQ消费者幂等(保证唯一)一样 解决方案: token 令牌 保证唯一的并且是临时的  过一段时间失效 分布式: redis+to ...

  5. 【从零开始搭建自己的.NET Core Api框架】(四)实战!带你半个小时实现接口的JWT授权验证

    系列目录 一.  创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...

  6. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  7. .NET CORE API 使用Postman中Post请求获取不到传参问题

    开发中遇到个坑 记录下. 使用Postman请求core api 接口时,按之前的使用方法(form-data , x-www-form-urlencoded)怎么设置都无法访问. 最后采用raw写入 ...

  8. IdentityServer4实现.Net Core API接口权限认证(快速入门)

    什么是IdentityServer4 官方解释:IdentityServer4是基于ASP.NET Core实现的认证和授权框架,是对OpenID Connect和OAuth 2.0协议的实现. 通俗 ...

  9. 详解ASP.NET Core API 的Get和Post请求使用方式

    上一篇文章帮助大家解决问题不彻底导致博友使用的时候还是遇到一些问题,欢迎一起讨论.所以下面重点详细讲解我们常用的Get和Post请求( 以.net core2.2的Http[Verb]为方向 ,推荐该 ...

随机推荐

  1. CF666E-Forensic Examination【广义SAM,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/CF666E 解题思路 给出一个串\(S\)和\(n\)个串\(T_i\).\(m\)次询问\(S_{a\sim b} ...

  2. P6657-[模板]LGV 引理

    正题 题目链接:https://www.luogu.com.cn/problem/P6657 题目大意 给出$n\times n$的棋盘,$m$个起点第$i$个为$(1,a_i)$,对应$m$个终点第 ...

  3. 【vue】使用 Video.js 播放视频

    目录 安装 引入 使用 参考文档 环境: vue 2.0+ element ui (这里的代码用了elmentui的按钮样式,可以不用elment ui的样式) 安装 在项目中安装 video.js. ...

  4. 浅谈机(J)惨(C)技巧——从入门到精通(?)

    JC总是无聊的机房中有意思的一个瞬间... 比如: 这个杰作由 ZSWBWYX 完成 你认为这只是AK-IOI吗?不!注意用户名...也是此人的杰作. 所以,在险恶的机房里,一定要保护好自己的账号. ...

  5. python 包(package)和模块(module)的创建和引入(import)

    python 包(package)和模块(module)的创建和引入(import) 名词解释 实际上,Python中的函数(Function).类(Class).模块(Module).包库(Pack ...

  6. $hadow$ocks与Privoxy基础原理

    $hadow$ocks与Privoxy基础原理 以下所有提到$hadow$ocks的均以ss指代 为什么要用ss呢? 在早期(如今绝大多数也是),对于互联网的访问流程是及其简单的:浏览器(或其他客户端 ...

  7. Azure Devops实践(5)- 构建springboot项目打包docker镜像及容器化部署

    使用Azure Devops构建java springboot项目,创建镜像并容器化部署 1.创建一个springboot项目,我用现有的项目 目录结构如下,使用provider项目 在根目录下添加D ...

  8. Hadoop面试题总结(三)——MapReduce

    1.谈谈Hadoop序列化和反序列化及自定义bean对象实现序列化? 1)序列化和反序列化 (1)序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输. (2) ...

  9. python反序列化1(__reduce__)

    part1:不求甚解的复现 对于服务端源码:    编写恶意序列化对象生成程序: 将生成的恶意序列化对象输入服务端user,使其执行系统命令.(上面那俩其实都行) part2:原理解释 b'xxx'是 ...

  10. 【Spring】IoC容器 - 依赖注入

    前言 上一篇文章已经学习了[依赖查找]相关的知识,这里详细的介绍一下[依赖注入]. 依赖注入 - 分类 因为自己是基于小马哥的脉络来学习,并且很认可小马哥梳理的分类方式,下面按照小马哥思想为[依赖注入 ...