詳解Redis如何優(yōu)雅地實(shí)現(xiàn)接口防刷
背景
最近在學(xué)習(xí)redis,想到了之前的寫的一個(gè)案例demo,實(shí)現(xiàn)了接口的流量防刷。主要是為了防止爬蟲爬取接口,當(dāng)然可以適用于那些需要進(jìn)行流控的系統(tǒng),shigen
畫了一張草圖展示主要的原理和過程:
首先用戶請求系統(tǒng)的接口,后端會有一個(gè)流控的攔截器,這里邊主要是去獲得請求的信息,用ip+URI作為redis的key,查詢在redis中記錄的次數(shù),如果次數(shù)大于規(guī)定的單位時(shí)間的訪問次數(shù),就認(rèn)為這是非法的請求了,就需要攔截了。那具體的代碼該怎么設(shè)計(jì)呢》?下邊是一份詳細(xì)的代碼案例。亮點(diǎn)在于:shigen
使用了一個(gè)注解,支持接口的個(gè)性化設(shè)置。
代碼實(shí)現(xiàn)
自定義ReteLimit
注解
package main.java.com.shigen.redis.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy, import java.lang.annotation.Target; /** * @author shigenfu * @date 2023/9/6 10:05 上午 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RateLimit { /** * 限定時(shí)間 * * @return 限定時(shí)間 */ int seconds() default 1; /** * 最大請求數(shù) * * @return 最大請求數(shù)! */ int max() default 1; }
其實(shí)就是兩個(gè)核心參數(shù)seconds
max
規(guī)定了單位時(shí)間內(nèi)的最大訪問次數(shù)。
攔截器rateLimitIntercept
/** * @author shigenfu * @date 2023/9/6 10:09 上午 */ @Component public class RateLimitIntercept extends HandlerInterceptorAdapter { @Resource private RedisTemplate<String, String> redisTemplate; public static final String RATE_LIMIT_KEY = "rl:", @Override public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws IOException{ // 請求是否是方法的請求 if (handler instanceof HandlerMethod){ HandlerMethod handlerMethod =(HandlerMethod) handler: // 獲得注解 RateLimit methodAnnotation = handlerMethod.getMethodAnnotation(RateLimit.class); if (methodAnnotation == null) { return true; } int seconds = methodAnnotation.seconds(); int max = methodAnnotation.max(); String key = RATE_LIMIT_KEY + request.getRemoteAddr()+ ":"+ request.getRequestURI(); String times = redisTemplate.opsForValue().get(key); if (times = null) { redisTemplate.opsForValue().set(key, String.value0f(1), seconds, TimeUnit.SECONDS); }else{ int timesInt = Integer.parseInt(times); if(timesInt < max){ redisTemplate.opsForValue().set(key, String.value0f(timesInt + 1), seconds, TimeUnit.SECONDs); }else{ response.sendError(429,"to many requests"); return false; } } } return true, } }
注冊到攔截器上
/** * @author shigenfu * @date 2023/9/6 11:30 上午 */ @Configuration public class WebConfig implements WebMvcConfigurer { @Resource private RateLimitIntercept rateLimitIntercept; @Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(rateLimitIntercept), } }
這一步很重要,不然我們自定義的攔截器會不生效。
測試類測試
/** * @author shigenfu * @date 2023/9/6 11:25 上午 */ @RestController @RequestMapping(value ="rate") public class RateLimitTestController { @GetMapping(value = "test") @RateLimit(seconds=10,max=2) public String test(){ return UUID.randomUUID().toString(); } }
這里主要是寫了一個(gè)接口實(shí)現(xiàn)測試,訪問的時(shí)候返回隨機(jī)生成的UUID字符串。為了測試的效果明顯,我在@RateLimit
上配置的是10s之內(nèi)只能允許2次請求。那現(xiàn)在開始測試吧!
測試
依舊用到的是ab
這個(gè)工具。
ab -c 2 -n 10 127.0.0.1:9000/rate/test
一起看看效果吧。
可以看到測試的報(bào)告,10個(gè)請求,8個(gè)失敗,2個(gè)成功,數(shù)據(jù)庫也存儲了對應(yīng)的key和value,很符合預(yù)期的效果。
頁面的錯(cuò)誤是這樣的,也很符合預(yù)期。
到此這篇關(guān)于詳解Redis如何優(yōu)雅地實(shí)現(xiàn)接口防刷的文章就介紹到這了,更多相關(guān)Redis接口防刷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis之常用數(shù)據(jù)結(jié)構(gòu)哈希表
這篇文章主要介紹了Redis常用的數(shù)據(jù)結(jié)構(gòu)哈希表,哈希表是一種保存鍵值對的數(shù)據(jù)結(jié)構(gòu),具有一定的參考價(jià)值,需要的朋友可以參考閱讀2023-04-04Redis的數(shù)據(jù)過期策略和數(shù)據(jù)淘汰策略
本文主要介紹了Redis的數(shù)據(jù)過期策略和數(shù)據(jù)淘汰策略,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02Redis數(shù)據(jù)導(dǎo)入導(dǎo)出以及數(shù)據(jù)遷移的4種方法詳解
這篇文章主要介紹了Redis數(shù)據(jù)導(dǎo)入導(dǎo)出以及數(shù)據(jù)遷移的4種方法詳解,需要的朋友可以參考下2020-02-02CentOS8.4安裝Redis6.2.6的詳細(xì)過程
本文給大家介紹CentOS8.4安裝Redis6.2.6的詳細(xì)過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-11-11詳解Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表
這篇文章主要介紹了Redis數(shù)據(jù)結(jié)構(gòu)中的跳躍表的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11redis哈希類型_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了redis哈希類型的常用方法及原理淺析,感興趣的朋友一起看看吧2017-08-08關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)詳解
Redis是一種高級key-value數(shù)據(jù)庫。它跟memcached類似,不過數(shù)據(jù)可以持久化,而且支持的數(shù)據(jù)類型很豐富。有字符串,鏈表、哈希、集合和有序集合5種。下面這篇文章主要給大家介紹了關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)的相關(guān)資料,需要的朋友可以參考下。2017-09-09