欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前言

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

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

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

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

本文主要講的是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ǔ)接口,都是通過限流來實(shí)現(xiàn)免費(fèi)與付費(fèi)直接的轉(zhuǎn)換。
  • 被各種系統(tǒng)廣泛調(diào)用的api接口,嚴(yán)重消耗網(wǎng)絡(luò)、內(nèi)存等資源,需要合理限流。

api限流實(shí)戰(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ù)庫索引(默認(rèn)為0)
    host: 127.0.0.1 # Redis服務(wù)器地址
    port: 6379 # Redis服務(wù)器連接端口
    password: 123456 # Redis服務(wù)器連接密碼(默認(rèn)為空)
    timeout: 2000  # 連接超時時間(毫秒)
    jedis:
      pool:
        max-active: 200         # 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
        max-idle: 20         # 連接池中的最大空閑連接
        min-idle: 0         # 連接池中的最小空閑連接
        max-wait: -1       # 連接池最大阻塞等待時間(使用負(fù)值表示沒有限制)

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è)置默認(rèn)的會將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;

二、實(shí)現(xiàn)限流

2.1 添加自定義AccessLimit注解

使用注解方式實(shí)現(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的方式對某一用戶的某一請求進(jìn)行唯一標(biāo)識
  • 每次訪問的時候判斷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 實(shí)例
            if (handler instanceof HandlerMethod) {
                // 強(qiáng)轉(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實(shí)現(xiàn)API接口防刷限流的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)Springboot Redis 接口防刷限流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Boot整合持久層之JdbcTemplate多數(shù)據(jù)源

    Spring?Boot整合持久層之JdbcTemplate多數(shù)據(jù)源

    持久層是JavaEE中訪問數(shù)據(jù)庫的核心操作,SpringBoot中對常見的持久層框架都提供了自動化配置,例如JdbcTemplate、JPA 等,MyBatis 的自動化配置則是MyBatis官方提供的。接下來分別向讀者介紹Spring Boot整合這持久層技術(shù)中的整合JdbcTemplate
    2022-08-08
  • Java  HttpURLConnection超時和IO異常處理

    Java HttpURLConnection超時和IO異常處理

    這篇文章主要介紹了Java HttpURLConnection超時和IO異常處理的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • 淺談Java并發(fā)編程之Lock鎖和條件變量

    淺談Java并發(fā)編程之Lock鎖和條件變量

    這篇文章主要介紹了淺談Java并發(fā)編程之Lock鎖和條件變量,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Fluent Mybatis實(shí)現(xiàn)環(huán)境隔離和租戶隔離

    Fluent Mybatis實(shí)現(xiàn)環(huán)境隔離和租戶隔離

    我們在實(shí)際的業(yè)務(wù)開發(fā)中,經(jīng)常會碰到環(huán)境邏輯隔離和租戶數(shù)據(jù)邏輯隔離的問題。本文就詳細(xì)的來介紹一下,感興趣的小伙伴們可以參考一下
    2021-08-08
  • springboot2 生產(chǎn)部署注意事項(xiàng)及示例代碼

    springboot2 生產(chǎn)部署注意事項(xiàng)及示例代碼

    這篇文章主要介紹了springboot2 生產(chǎn)部署注意事項(xiàng)及示例代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • Spring中的Bean對象初始化詳解

    Spring中的Bean對象初始化詳解

    這篇文章主要介紹了Spring中的Bean對象初始化詳解,我們也可以根據(jù)Java語言的特性猜測到其很有可能是通過反射機(jī)制來完成Bean的初始化操作,接下來我們一步一步的剖析Spring對Bean的初始化操作,需要的朋友可以參考下
    2023-12-12
  • 鄰接表無向圖的Java語言實(shí)現(xiàn)完整源碼

    鄰接表無向圖的Java語言實(shí)現(xiàn)完整源碼

    這篇文章主要介紹了鄰接表無向圖的Java語言實(shí)現(xiàn)完整源碼,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Spring Boot2中如何優(yōu)雅地個性化定制Jackson實(shí)現(xiàn)示例

    Spring Boot2中如何優(yōu)雅地個性化定制Jackson實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Spring Boot2中如何優(yōu)雅地個性化定制Jackson實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • IDEA正則表達(dá)式全局搜索圖文教程

    IDEA正則表達(dá)式全局搜索圖文教程

    當(dāng)您要搜索和替換特定的文本模式時,請使用正則表達(dá)式,下面這篇文章主要給大家介紹了關(guān)于IDEA正則表達(dá)式全局搜索的相關(guān)資料,文中通過代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • 詳解SpringBoot接收參數(shù)的五種形式

    詳解SpringBoot接收參數(shù)的五種形式

    在Spring Boot中,接收參數(shù)可以通過多種方式實(shí)現(xiàn),本文給大家介紹了SpringBoot接收參數(shù)的五種形式,并通過代碼和圖文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03

最新評論