精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一篇文章讓你了解如何優(yōu)雅地處理重復(fù)請求

開發(fā) 前端
本文討論的是如何在服務(wù)端優(yōu)雅地統(tǒng)一處理這種情況,如何禁止用戶重復(fù)點擊等客戶端操作不在本文的討論范疇。

對于一些用戶請求,在某些情況下是可能重復(fù)發(fā)送的,如果是查詢類操作并無大礙,但其中有些是涉及寫入操作的,一旦重復(fù)了,可能會導(dǎo)致很嚴重的后果,例如交易的接口如果重復(fù)請求可能會重復(fù)下單。

重復(fù)的場景有可能是:

  • 黑客攔截了請求,重放
  • 前端/客戶端因為某些原因請求重復(fù)發(fā)送了,或者用戶在很短的時間內(nèi)重復(fù)點擊了
  • 網(wǎng)關(guān)重發(fā)
  • ….

本文討論的是如何在服務(wù)端優(yōu)雅地統(tǒng)一處理這種情況,如何禁止用戶重復(fù)點擊等客戶端操作不在本文的討論范疇。

利用唯一請求編號去重

可能會想到的是,只要請求有唯一的請求編號,那么就能借用Redis做這個去重——只要這個唯一請求編號在redis存在,證明處理過,那么就認為是重復(fù)的

代碼大概如下:

String KEY = "REQ12343456788";//請求唯一編號
long expireTime = 1000;// 1000毫秒過期,1000ms內(nèi)的重復(fù)請求會認為重復(fù)
long expireAt = System.currentTimeMillis() + expireTime;
String val = "expireAt@" + expireAt;

//redis key還存在的話要就認為請求是重復(fù)的
Boolean firstSet = stringRedisTemplate.execute((RedisCallback<Boolean>) 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值已存在,認為是重復(fù)了
isConsiderDup = true;
}

業(yè)務(wù)參數(shù)去重

上面的方案能解決具備唯一請求編號的場景,例如每次寫請求之前都是服務(wù)端返回一個唯一編號給客戶端,客戶端帶著這個請求號做請求,服務(wù)端即可完成去重攔截。

但是,很多的場景下,請求并不會帶這樣的唯一編號!那么我們能否針對請求的參數(shù)作為一個請求的標(biāo)識呢?

先考慮簡單的場景,假設(shè)請求參數(shù)只有一個字段reqParam,我們可以利用以下標(biāo)識去判斷這個請求是否重復(fù)。用戶ID:接口名:請求參數(shù)

String KEY = "dedup:U="+userId + "M=" + method + "P=" + reqParam;

那么當(dāng)同一個用戶訪問同一個接口,帶著同樣的reqParam過來,我們就能定位到他是重復(fù)的了。

但是問題是,我們的接口通常不是這么簡單,以目前的主流,我們的參數(shù)通常是一個JSON。那么針對這種場景,我們怎么去重呢?

計算請求參數(shù)的摘要作為參數(shù)標(biāo)識

假設(shè)我們把請求參數(shù)(JSON)按KEY做升序排序,排序后拼成一個字符串,作為KEY值呢?但這可能非常的長,所以我們可以考慮對這個字符串求一個MD5作為參數(shù)的摘要,以這個摘要去取代reqParam的位置。

String KEY = "dedup:U="+userId + "M=" + method + "P=" + reqParamMD5;

這樣,請求的唯一標(biāo)識就打上了!

注:MD5理論上可能會重復(fù),但是去重通常是短時間窗口內(nèi)的去重(例如一秒),一個短時間內(nèi)同一個用戶同樣的接口能拼出不同的參數(shù)導(dǎo)致一樣的MD5幾乎是不可能的。關(guān)注公眾號:碼猿技術(shù)專欄,回復(fù)關(guān)鍵詞:“Spring Cloud 進階”,獲取阿里內(nèi)部的Spring Cloud Alibaba 進階手冊!

繼續(xù)優(yōu)化,考慮剔除部分時間因子

上面的問題其實已經(jīng)是一個很不錯的解決方案了,但是實際投入使用的時候可能發(fā)現(xiàn)有些問題:某些請求用戶短時間內(nèi)重復(fù)的點擊了(例如1000毫秒發(fā)送了三次請求),但繞過了上面的去重判斷(不同的KEY值)。

原因是這些請求參數(shù)的字段里面,是帶時間字段的,這個字段標(biāo)記用戶請求的時間,服務(wù)端可以借此丟棄掉一些老的請求(例如5秒前)。如下面的例子,請求的其他參數(shù)是一樣的,除了請求時間相差了一秒:

//兩個請求一樣,但是請求時間差一秒
String req = "{\n" +
"\"requestTime\" :\"20190101120001\",\n" +
"\"requestValue\" :\"1000\",\n" +
"\"requestKey\" :\"key\"\n" +
"}";

String req2 = "{\n" +
"\"requestTime\" :\"20190101120002\",\n" +
"\"requestValue\" :\"1000\",\n" +
"\"requestKey\" :\"key\"\n" +
"}";

這種請求,我們也很可能需要擋住后面的重復(fù)請求。所以求業(yè)務(wù)參數(shù)摘要之前,需要剔除這類時間字段。還有類似的字段可能是GPS的經(jīng)緯度字段(重復(fù)請求間可能有極小的差別)。

請求去重工具類,Java實現(xiàn)

public class ReqDedupHelper {

/**
*
* @param reqJSON 請求的參數(shù),這里通常是JSON
* @param excludeKeys 請求參數(shù)里面要去除哪些字段再求摘要
* @return 去除參數(shù)的MD5摘要
*/
public String dedupParamMD5(final String reqJSON, String... excludeKeys) {
String decreptParam = reqJSON;

TreeMap paramTreeMap = JSON.parseObject(decreptParam, TreeMap.class);
if (excludeKeys!=null) {
List<String> dedupExcludeKeys = Arrays.asList(excludeKeys);
if (!dedupExcludeKeys.isEmpty()) {
for (String dedupExcludeKey : dedupExcludeKeys) {
paramTreeMap.remove(dedupExcludeKey);
}
}
}

String paramTreeMapJSON = JSON.toJSONString(paramTreeMap);
String md5deDupParam = jdkMD5(paramTreeMapJSON);
log.debug("md5deDupParam = {}, excludeKeys = {} {}", md5deDupParam, Arrays.deepToString(excludeKeys), paramTreeMapJSON);
return md5deDupParam;
}

private static String jdkMD5(String src) {
String res = null;
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] mdBytes = messageDigest.digest(src.getBytes());
res = DatatypeConverter.printHexBinary(mdBytes);
} catch (Exception e) {
log.error("",e);
}
return res;
}
}

下面是一些測試日志:

public static void main(String[] args) {
//兩個請求一樣,但是請求時間差一秒
String req = "{\n" +
"\"requestTime\" :\"20190101120001\",\n" +
"\"requestValue\" :\"1000\",\n" +
"\"requestKey\" :\"key\"\n" +
"}";

String req2 = "{\n" +
"\"requestTime\" :\"20190101120002\",\n" +
"\"requestValue\" :\"1000\",\n" +
"\"requestKey\" :\"key\"\n" +
"}";

//全參數(shù)比對,所以兩個參數(shù)MD5不同
String dedupMD5 = new ReqDedupHelper().dedupParamMD5(req);
String dedupMD52 = new ReqDedupHelper().dedupParamMD5(req2);
System.out.println("req1MD5 = "+ dedupMD5+" , req2MD5="+dedupMD52);

//去除時間參數(shù)比對,MD5相同
String dedupMD53 = new ReqDedupHelper().dedupParamMD5(req,"requestTime");
String dedupMD54 = new ReqDedupHelper().dedupParamMD5(req2,"requestTime");
System.out.println("req1MD5 = "+ dedupMD53+" , req2MD5="+dedupMD54);

}

日志輸出:

req1MD5 = 9E054D36439EBDD0604C5E65EB5C8267 , req2MD5=A2D20BAC78551C4CA09BEF97FE468A3F
req1MD5 = C2A36FED15128E9E878583CAAAFEFDE9 , req2MD5=C2A36FED15128E9E878583CAAAFEFDE9

日志說明:

  • 一開始兩個參數(shù)由于requestTime是不同的,所以求去重參數(shù)摘要的時候可以發(fā)現(xiàn)兩個值是不一樣的
  • 第二次調(diào)用的時候,去除了requestTime再求摘要(第二個參數(shù)中傳入了”requestTime”),則發(fā)現(xiàn)兩個摘要是一樣的,符合預(yù)期。

總結(jié)

至此,我們可以得到完整的去重解決方案,如下:

String userId= "12345678";//用戶
String method = "pay";//接口名
String dedupMD5 = new ReqDedupHelper().dedupParamMD5(req,"requestTime");//計算請求參數(shù)摘要,其中剔除里面請求時間的干擾
String KEY = "dedup:U=" + userId + "M=" + method + "P=" + dedupMD5;

long expireTime = 1000;// 1000毫秒過期,1000ms內(nèi)的重復(fù)請求會認為重復(fù)
long expireAt = System.currentTimeMillis() + expireTime;
String val = "expireAt@" + expireAt;

// NOTE:直接SETNX不支持帶過期時間,所以設(shè)置+過期不是原子操作,極端情況下可能設(shè)置了就不過期了,后面相同請求可能會誤以為需要去重,所以這里使用底層API,保證SETNX+過期時間是原子操作
Boolean firstSet = stringRedisTemplate.execute((RedisCallback<Boolean>) 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 {
isConsiderDup = true;
}


責(zé)任編輯:武曉燕 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2022-08-09 08:00:55

AWS安全API

2019-09-11 08:52:24

MVCMVPMVVM

2023-07-28 07:14:13

2020-10-09 08:15:11

JsBridge

2021-06-30 00:20:12

Hangfire.NET平臺

2023-05-12 08:19:12

Netty程序框架

2021-05-11 10:01:54

avaScript錯誤處理

2021-02-02 18:39:05

JavaScript

2021-01-29 18:41:16

JavaScript函數(shù)語法

2021-06-04 09:56:01

JavaScript 前端switch

2019-01-09 10:04:16

2020-11-10 10:48:10

JavaScript屬性對象

2023-05-08 08:21:15

JavaNIO編程

2021-03-09 14:04:01

JavaScriptCookie數(shù)據(jù)

2021-09-27 09:18:30

ListIterato接口方法

2021-01-26 23:46:32

JavaScript數(shù)據(jù)結(jié)構(gòu)前端

2024-01-30 13:47:45

2021-02-26 20:01:57

SVG濾鏡元素

2023-07-30 15:18:54

JavaScript屬性

2021-05-18 08:30:42

JavaScript 前端JavaScript時
點贊
收藏

51CTO技術(shù)棧公眾號

男人天堂2024| 亚洲欧洲三级| 日本一区二区欧美| 日本福利一区| 91黄色免费看| 欧美日韩一区二区三区电影| 性做久久久久久久久久| 国产精品美女久久久浪潮软件| 亚洲嫩模很污视频| 中日韩av在线播放| 国产黄色大片在线观看| 国产亚洲精品bt天堂精选| 国产精品亚洲片夜色在线| 国产va在线播放| 欧美一级一片| 欧美日韩一区二区在线视频| 在线观看免费黄色片| 天天干视频在线观看| 免费在线一区观看| 欧美夫妻性视频| 国产毛片欧美毛片久久久| 欧美9999| 欧美影片第一页| www.日本少妇| 日本网站在线免费观看视频| 不卡电影一区二区三区| 国产在线视频2019最新视频| 日本韩国欧美中文字幕| 小小影院久久| 国产亚洲欧洲高清| 中文字幕一区二区三区乱码不卡| 成人在线视频免费看| 精品动漫一区二区| 亚洲精品国偷自产在线99热| 亚洲小说欧美另类婷婷| 无码精品在线观看| 性人久久久久| 欧美一区二区三区四区在线观看| 久久久久免费精品| 91禁在线看| 亚洲人吸女人奶水| 日韩福利影院| 你懂的在线观看视频网站| 极品尤物av久久免费看| 国产精品久久久久久久久久新婚 | 日韩精品一区二区三区四区五区 | 小h片在线观看| 亚洲男人的天堂在线aⅴ视频| 国产亚洲精品久久飘花| 午夜老司机福利| 黄一区二区三区| 国产精品视频永久免费播放 | 99青草视频在线播放视| 26uuu国产电影一区二区| 国产精品二区在线| 国产91视频在线| 激情六月婷婷综合| 国产欧美一区二区三区在线| 中国女人一级一次看片| 日本v片在线高清不卡在线观看| 欧美一级视频在线观看| 国产91精品一区| 99热这里只有成人精品国产| 性色av香蕉一区二区| 国产第一页第二页| 亚洲电影在线| 欧美性资源免费| 欧美日韩一二三四区| 久久精品三级| 国产精品毛片a∨一区二区三区|国| 无码人妻久久一区二区三区不卡| 美女网站久久| 国产97在线播放| 奴色虐av一区二区三区| 免费不卡在线视频| 国产欧美日韩综合精品| 国产三级按摩推拿按摩| 国产精品亚洲专一区二区三区| 亚洲aⅴ日韩av电影在线观看| 国产欧美久久久| 国产福利一区二区三区视频 | 四虎av在线| 成人无码av片在线观看| 高清免费日韩| 亚洲综合欧美激情| 国产精品高潮久久| 欧美三级视频在线| 欧美激情亚洲视频| 日本美女视频网站| 国偷自产视频一区二区久| 亚洲国产成人精品女人久久久 | 老司机精品福利在线观看| 你懂的免费在线观看| 国产精品无人区| 男女h黄动漫啪啪无遮挡软件| 日本伦理一区二区| 欧美日韩中文字幕日韩欧美| 邪恶网站在线观看| 91麻豆精品激情在线观看最新| 日韩精品免费一线在线观看| 日本精品久久久久中文| 国产一区日韩欧美| 国产97在线视频| www.蜜臀av| 久久久另类综合| 国产精品12p| 中老年在线免费视频| 欧美丰满一区二区免费视频| 亚洲啪av永久无码精品放毛片 | 日韩福利在线视频| 免费观看成人高潮| 一区二区三区日韩欧美| 精品国产免费av| yellow在线观看网址| 国产又粗又猛又黄视频| 福利视频亚洲| 欧美一区二区视频在线观看 | 欧美成人app| 国产精品传媒视频| 精品国产一二三四区| 欧美aaaaaaaa| 日韩精品中文字幕在线| 午夜爱爱毛片xxxx视频免费看| 在线综合亚洲| 亚洲自拍av在线| 国产视频二区在线观看| 亚洲风情在线资源站| 成人日韩在线视频| 宅男在线一区| 久久久久久这里只有精品| 又色又爽又黄无遮挡的免费视频| av亚洲精华国产精华精华| 在线看成人av电影| 欧美三区四区| 亚洲美女中文字幕| 国产无套粉嫩白浆内谢| 韩国成人精品a∨在线观看| 日韩精品欧美在线| 日韩电影大全网站| 日韩av中文字幕在线免费观看| 日本a级片视频| 裸体一区二区三区| 日韩av一区二区三区在线 | 亚洲视频一二区| 日本xxxxxxx免费视频| 欧美一区二区三区红桃小说| 久久久久久美女| 亚洲国产精彩视频| 亚洲人成电影网站色mp4| 天天操天天摸天天爽| 伊人久久大香线蕉综合网站 | 国产精品一区二区三区四区| 亚洲天堂电影网| 日本.亚洲电影| 国产一区二区激情| 波多野结衣一二区| 欧美激情中文字幕| 亚洲综合色在线观看| 久久影院100000精品| 国产精品久久久一区| 国产高清在线观看| 欧美性猛交xxxxxx富婆| 91在线无精精品白丝| 日本不卡在线视频| 亚洲欧洲在线一区| 久久91视频| 成人97在线观看视频| 国产夫妻性生活视频| 一区二区三区欧美日| 日本xxxx免费| 亚洲二区在线| 欧美一区二区三区电影在线观看| xxxx日本少妇| 老司机午夜精品| 精品免费99久久| 亚洲一区视频在线| 亚洲变态欧美另类捆绑| 人妻少妇偷人精品久久久任期| 日韩天堂在线| 久久久精品国产免大香伊 | 欧美黄色精品| 成人免费看片网址| 国产在线天堂www网在线观看| 99精品视频免费在线观看| 亚洲一区二区三区四区五区午夜 | 在线观看亚洲| 亚洲高清久久久久久| 欧美三级视频网站| 精品一区二区免费在线观看| 超碰在线免费观看97| 爱高潮www亚洲精品| 欧美综合在线第二页| av中文资源在线| 日韩欧美中文一区二区| 日韩精品人妻中文字幕| 欧美国产精品中文字幕| 人妻体体内射精一区二区| 在线午夜精品| 中国成人亚色综合网站| 久久99精品国产自在现线| 国产精品久久久999| 性xxxxfjsxxxxx欧美| 亚洲精品在线看| 国产人妖一区二区| 色婷婷av一区二区三区之一色屋| 极品魔鬼身材女神啪啪精品| 91毛片在线观看| 日韩精品视频网址| 天堂资源在线中文精品| 一本大道东京热无码aⅴ| 蜜桃成人av| 51国产成人精品午夜福中文下载 | 一区二区高清视频在线观看| 熟妇高潮精品一区二区三区| 国产精品白丝jk黑袜喷水| 最近免费中文字幕中文高清百度| 91精品啪在线观看国产18| 美乳视频一区二区| 在线精品视频一区| 成人激情视频在线播放| 欧美黑人一区| 97精品视频在线| 亚洲七七久久综合桃花剧情介绍| 在线精品视频视频中文字幕| 天天躁日日躁狠狠躁伊人| 91精品国产欧美一区二区成人| 亚洲精品中文字幕乱码三区91| 亚洲一区av在线| 中文国语毛片高清视频| 久久久久久久电影| 波多野结衣先锋影音| 粉嫩嫩av羞羞动漫久久久| 天天色天天综合网| 喷水一区二区三区| 国产第一页视频| 99在线精品免费视频九九视| 男人添女人下部视频免费| 亚洲91精品| 伊人久久av导航| 日韩av片子| 亚洲aⅴ天堂av在线电影软件| 日韩av网站在线免费观看| 国产精品日韩一区二区免费视频| 国产精品视频一区视频二区| 91精品国产综合久久久久久蜜臀| 国产一区二区三区影视| 国产精品va在线播放| 日韩伦理三区| 日韩av第一页| 欧美人与性动交xxⅹxx| 国产97免费视| 素人啪啪色综合| 国产精品尤物福利片在线观看| 中文字幕av一区二区三区佐山爱| 8x拔播拔播x8国产精品| 涩涩涩视频在线观看| 26uuu亚洲国产精品| 一区二区精品伦理...| 欧美一级免费看| 国产精品一区二区av影院萌芽| 欧美最猛性xxxxx(亚洲精品)| 小视频免费在线观看| www.日韩视频| 国产精品视频免费一区| 成人看片免费| 欧美xxxx18国产| 中文国产字幕在线观看| 欧美大胆在线视频| 免费电影视频在线看| 国外成人免费在线播放| 日韩脚交footjobhdboots| 日本伊人精品一区二区三区介绍| 最新日韩精品| 国产精品女人久久久久久| 九九九在线观看视频| 午夜成人鲁丝片午夜精品| 在线日韩一区二区| 亚洲在线观看av| 欧美日韩高清一区二区三区| 亚洲精品91天天久久人人| 国产综合欧美| 在线国产伦理一区| 国产精品国码视频| 不卡影院一区二区| 久久精品国产999大香线蕉| 无码人妻少妇色欲av一区二区| 成人app下载| 蜜桃传媒一区二区亚洲| 日韩一区日韩二区| 精品在线视频免费| 日本大香伊一区二区三区| 国产精品一区二区av白丝下载| 精品国产91亚洲一区二区三区婷婷| 色在线免费视频| 日韩在线视频国产| 2020日本在线视频中文字幕| 国产精品27p| 日韩一区二区三区精品视频第3页| 国产一区二区三区四区hd| 欧美特黄一级大片| av片在线免费| 免费欧美在线视频| 亚洲图片欧美另类| 国产精品三级久久久久三级| 久久精品国产av一区二区三区| 在线欧美小视频| 免费av网站在线播放| 在线色欧美三级视频| 欧美xxxx黑人又粗又长| 国产成人精品午夜| www.亚洲一二| 在线看视频不卡| 丝袜a∨在线一区二区三区不卡 | 999福利在线视频| 国产日本欧美一区| 亚洲精品进入| 久久www视频| 久久国产精品免费| 欧美性猛交xxxx乱| 精品国产老师黑色丝袜高跟鞋| 国产露脸91国语对白| 一区二区三区黄色| 免费一二一二在线视频| 91精品婷婷国产综合久久蝌蚪| 欧美三级情趣内衣| 成人免费aaa| 夫妻av一区二区| 日韩欧美国产成人精品免费| 日本高清视频一区二区| 黄色小视频免费在线观看| 久久久精品国产一区二区| 午夜av成人| 欧美一级二级三级九九九| 亚洲激情网站| 美女露出粉嫩尿囗让男人桶| 亚洲欧美另类在线| 国产三级在线观看视频| 日韩网站在线观看| 久久91视频| 一本一本a久久| 日韩国产精品久久久久久亚洲| xxxx黄色片| 香蕉加勒比综合久久| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的| 欧美另类暴力丝袜| 免费欧美网站| 日本免费成人网| 国产91丝袜在线播放九色| 在线免费日韩av| 精品国产乱码久久久久久图片| 丝袜美腿av在线| 99久久自偷自偷国产精品不卡| a级片在线免费| 欧美熟乱第一页| 亚洲 小说区 图片区 都市| 国内精品视频在线| 国内精品麻豆美女在线播放视频 | 欧美—级a级欧美特级ar全黄| 成年网站免费在线观看| 日本视频在线一区| 国产三级黄色片| 欧美三级电影网站| 9191在线| 成人免费高清完整版在线观看| 久久一区91| 欧美日本国产在线| 稀缺小u女呦精品呦| 岛国精品在线观看| 久久成人国产精品入口| 欧美xxxx老人做受| 国产精选在线| 欧美高清视频一区| 日韩精品免费观看视频| 国产精品午夜视频| 99精品国产一区二区三区| 午夜不卡福利视频| 一区二区在线观看免费视频播放| 亚洲高清视频网站| 51视频国产精品一区二区| 欧美色婷婷久久99精品红桃| 日日躁夜夜躁aaaabbbb| 一级特黄大欧美久久久| 深夜福利视频一区| 国产欧美精品久久久| 黄色成人91| 久久精品视频18| 欧美一区二区高清| 一区二区三区短视频| 一区二区三区四区| av影院午夜一区| 亚洲图片欧美在线| 久久久久久97| 成人6969www免费视频| 超碰在线超碰在线| 欧美视频中文字幕在线| 免费大片在线观看www| 国产一区二区无遮挡| 日本欧美一区二区在线观看| 欧美日韩亚洲国产另类| 亚洲日本欧美日韩高观看|