最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot+Redis實現(xiàn)API接口防刷限流的項目實踐

 更新時間:2024年07月12日 09:49:25   作者:憂傷夏天的風(fēng)  
本文主要介紹了Springboot+Redis實現(xiàn)API接口防刷限流的項目實踐,通過限流可以讓系統(tǒng)維持在一個相對穩(wěn)定的狀態(tài),為更多的客戶提供服務(wù),具有一定的參考價值,感興趣的可以了解一下

前言

在開發(fā)分布式高并發(fā)系統(tǒng)時有三把利器用來保護系統(tǒng):緩存、降級、限流。

緩存:緩存的目的是提升系統(tǒng)訪問速度和增大系統(tǒng)處理容量

降級:降級是當服務(wù)出現(xiàn)問題或者影響到核心流程時,需要暫時屏蔽掉,待高峰或者問題解決后再打開

限流:限流的目的是通過對并發(fā)訪問/請求進行限速,或者對一個時間窗口內(nèi)的請求進行限速來保護系統(tǒng),一旦達到限制速率則可以拒絕服務(wù)、排隊或等待、降級等處理

本文主要講的是api接口限流相關(guān)內(nèi)容,雖然不是論述高并發(fā)概念中的限流, 不過道理都差不多。通過限流可以讓系統(tǒng)維持在一個相對穩(wěn)定的狀態(tài),為更多的客戶提供服務(wù)。

api接口的限流主要應(yīng)用場景有:

  • 電商系統(tǒng)(特別是6.18、雙11等)中的秒殺活動,使用限流防止使用軟件惡意刷 單;
  • 各種基礎(chǔ)api接口限流:例如天氣信息獲取,IP對應(yīng)城市接口,百度、騰訊等對外提供的基礎(chǔ)接口,都是通過限流來實現(xiàn)免費與付費直接的轉(zhuǎn)換。
  • 被各種系統(tǒng)廣泛調(diào)用的api接口,嚴重消耗網(wǎng)絡(luò)、內(nèi)存等資源,需要合理限流。

api限流實戰(zhàn)

一、SpringBoot中集成Redis

SpringBoot中集成Redis相對比較簡單,步驟如下:

1.1 引入Redis依賴

<!--springboot redis依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

1.2 在application.yml中配置Redis

spring:
  redis:
    database: 3 # Redis數(shù)據(jù)庫索引(默認為0)
    host: 127.0.0.1 # Redis服務(wù)器地址
    port: 6379 # Redis服務(wù)器連接端口
    password: 123456 # Redis服務(wù)器連接密碼(默認為空)
    timeout: 2000  # 連接超時時間(毫秒)
    jedis:
      pool:
        max-active: 200         # 連接池最大連接數(shù)(使用負值表示沒有限制)
        max-idle: 20         # 連接池中的最大空閑連接
        min-idle: 0         # 連接池中的最小空閑連接
        max-wait: -1       # 連接池最大阻塞等待時間(使用負值表示沒有限制)

1.3 配置RedisTemplate

/**
 * @Description: redis配置類
 * @Author oyc
 * @Date 2020/4/22 11:50 下午
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * RedisTemplate相關(guān)配置
     * 使redis支持插入對象
     *
     * @param factory
     * @return 方法緩存 Methods the cache
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置連接工廠
        template.setConnectionFactory(factory);
        // 設(shè)置key的序列化器
        template.setKeySerializer(new StringRedisSerializer());
        // 設(shè)置value的序列化器
        //使用Jackson 2,將對象序列化為JSON
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //json轉(zhuǎn)對象類,不設(shè)置默認的會將json轉(zhuǎn)成hashmap
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }
}

以上,已經(jīng)完成Redis的集成,后續(xù)使用可以直接注入RedisTemplate(具體可參考另一篇博客:https://blog.csdn.net/u014553029/article/details/106087846),如下所示:

@Autowired
private RedisTemplate<String, Object> redisTemplate;

二、實現(xiàn)限流

2.1 添加自定義AccessLimit注解

使用注解方式實現(xiàn)接口的限流操作,方便而優(yōu)雅。

/**
 * @Description:
 * @Author oyc
 * @Date 2020/10/22 11:16 下午
 */
@Inherited
@Documented
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {

    /**
     * 指定second 時間內(nèi) API請求次數(shù)
     */
    int maxCount() default 5;

    /**
     * 請求次數(shù)的指定時間范圍  秒數(shù)(redis數(shù)據(jù)過期時間)
     */
    int second() default 60;
}

2.2 編寫攔截器

限流的思路

  • 通過路徑:ip的作為key,訪問次數(shù)為value的方式對某一用戶的某一請求進行唯一標識
  • 每次訪問的時候判斷key是否存在,是否count超過了限制的訪問次數(shù)
  • 若訪問超出限制,則應(yīng)response返回msg:請求過于頻繁給前端予以展示
/**
 * @Description: 訪問攔截器
 * @Author oyc
 * @Date 2020/10/22 11:20 下午
 */
@Component
public class AccessLimitInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {// Handler 是否為 HandlerMethod 實例
            if (handler instanceof HandlerMethod) {
                // 強轉(zhuǎn)
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                // 獲取方法
                Method method = handlerMethod.getMethod();
                // 是否有AccessLimit注解
                if (!method.isAnnotationPresent(AccessLimit.class)) {
                    return true;
                }
                // 獲取注解內(nèi)容信息
                AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);
                if (accessLimit == null) {
                    return true;
                }
                int seconds = accessLimit.second();
                int maxCount = accessLimit.maxCount();

                // 存儲key
                String key = request.getRemoteAddr() + ":" + request.getContextPath() + ":" + request.getServletPath();

                // 已經(jīng)訪問的次數(shù)
                Integer count = (Integer) redisTemplate.opsForValue().get(key);
                System.out.println("已經(jīng)訪問的次數(shù):" + count);
                if (null == count || -1 == count) {
                    redisTemplate.opsForValue().set(key, 1, seconds, TimeUnit.SECONDS);
                    return true;
                }

                if (count < maxCount) {
                    redisTemplate.opsForValue().increment(key);
                    return true;
                }

                if (count >= maxCount) {
                    logger.warn("請求過于頻繁請稍后再試");
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            logger.warn("請求過于頻繁請稍后再試");
            e.printStackTrace();
        }
        return true;
    }
}

2.3 注冊攔截器并配置攔截路徑和不攔截路徑

/**
 * @Description: 訪問攔截器配置
 * @Author oyc
 * @Date 2020/10/22 11:34 下午
 */
@Configuration
public class IntercepterConfig  implements WebMvcConfigurer {

    @Autowired
    private AccessLimitInterceptor accessLimitInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(accessLimitInterceptor)
                .addPathPatterns("/**").excludePathPatterns("/static/**","/login.html","/user/login");
    }
}

2.4 使用AccessLimit

/**
 * @Description:
 * @Author oyc
 * @Date 2020/10/22 11:36 下午
 */
@RestController
@RequestMapping("access")
public class AccessLimitController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 限流測試
     */
    @GetMapping
    @AccessLimit(maxCount = 3,second = 60)
    public String limit(HttpServletRequest request) {
        logger.error("Access Limit Test");
        return "限流測試";
    }

}

2.4 測試

源碼傳送門:https://github.com/oycyqr/springboot-learning-demo/tree/master/springboot-validated

到此這篇關(guān)于Springboot+Redis實現(xiàn)API接口防刷限流的項目實踐的文章就介紹到這了,更多相關(guān)Springboot Redis 接口防刷限流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot去除內(nèi)嵌tomcat的實現(xiàn)

    SpringBoot去除內(nèi)嵌tomcat的實現(xiàn)

    這篇文章主要介紹了SpringBoot去除內(nèi)嵌tomcat的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Springboot的application.properties或application.yml環(huán)境的指定運行與配置方式

    Springboot的application.properties或application.yml環(huán)境的指定運行與配置方

    本文主要介紹了Spring?Boot中配置文件的多種使用方式,包括配置文件的命名、激活、路徑指定以及優(yōu)先級,并結(jié)合示例進行了詳細說明
    2025-11-11
  • spring?boot?validation參數(shù)校驗與分組嵌套各種類型及使用小結(jié)

    spring?boot?validation參數(shù)校驗與分組嵌套各種類型及使用小結(jié)

    參數(shù)校驗基本上是controller必做的事情,畢竟前端傳過來的一切都不可信,validation可以簡化這一操作,這篇文章主要介紹了spring?boot?validation參數(shù)校驗分組嵌套各種類型及使用小結(jié),需要的朋友可以參考下
    2023-09-09
  • SpringBoot2.6.x升級后循環(huán)依賴及Swagger無法使用問題

    SpringBoot2.6.x升級后循環(huán)依賴及Swagger無法使用問題

    這篇文章主要為大家介紹了SpringBoot2.6.x升級后循環(huán)依賴及Swagger無法使用問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Java?PTA?計算3到7位?水仙花數(shù)實例

    Java?PTA?計算3到7位?水仙花數(shù)實例

    這篇文章主要介紹了Java?PTA?計算3到7位?水仙花數(shù)實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 全解析Spring Cloud之負載均衡之LoadBalance

    全解析Spring Cloud之負載均衡之LoadBalance

    這篇文章主要介紹了全解析Spring Cloud之負載均衡之LoadBalance的相關(guān)資料,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2025-05-05
  • Springboot的jak安裝與配置實踐

    Springboot的jak安裝與配置實踐

    本文介紹了在Windows、macOS和Linux系統(tǒng)下安裝JDK的方法,包括下載、安裝、配置環(huán)境變量以及驗證安裝步驟,不同操作系統(tǒng)對應(yīng)不同下載鏈接及安裝方式,配置環(huán)境變量需要修改系統(tǒng)屬性或.bash_profile文件,驗證安裝通過命令行檢查Java版本
    2026-04-04
  • 詳解Java中的日期類

    詳解Java中的日期類

    這篇文章主要介紹了Java中的日期類的相關(guān)資料,幫助大家更好的利用Java處理時間,感興趣的朋友可以了解下
    2020-10-10
  • Java中id,pid格式數(shù)據(jù)轉(zhuǎn)樹和森林結(jié)構(gòu)工具類實現(xiàn)

    Java中id,pid格式數(shù)據(jù)轉(zhuǎn)樹和森林結(jié)構(gòu)工具類實現(xiàn)

    本文主要介紹了Java中id,pid格式數(shù)據(jù)轉(zhuǎn)樹和森林結(jié)構(gòu)工具類實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 詳解Spring Boot讀取配置文件與配置文件優(yōu)先級

    詳解Spring Boot讀取配置文件與配置文件優(yōu)先級

    這篇文章主要介紹了詳解Spring Boot讀取配置文件與配置文件優(yōu)先級,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08

最新評論

探索| 南江县| 长岛县| 西充县| 宕昌县| 图木舒克市| 故城县| 天镇县| 文山县| 民县| 松潘县| 潢川县| 威远县| 庆城县| 泉州市| 宁陵县| 崇信县| 白朗县| 阜新市| 子洲县| 启东市| 礼泉县| 克拉玛依市| 徐水县| 张家港市| 东海县| 太康县| 理塘县| 天气| 阿城市| 黄平县| 浑源县| 德安县| 新建县| 嵊州市| 阿合奇县| 稷山县| 永济市| 大余县| 分宜县| 太和县|