亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

redis+lua實(shí)現(xiàn)限流的項(xiàng)目實(shí)踐

 更新時(shí)間:2023年10月30日 15:29:28   作者:Best_Liu~  
redis有很多限流的算法(比如:令牌桶,計(jì)數(shù)器,時(shí)間窗口)等,在分布式里面進(jìn)行限流的話,我們則可以使用redis+lua腳本進(jìn)行限流,下面就來(lái)介紹一下redis+lua實(shí)現(xiàn)限流

1、需要引入Redis的maven坐標(biāo)

<!--redis和 springboot集成的包 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.3.0.RELEASE</version>
</dependency>

2、redis配置

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

3、新建腳本放在該項(xiàng)目的 resources 目錄下,新建 limit.lua

local key = KEYS[1] --限流KEY 
local limit = tonumber(ARGV[1]) --限流大小 
local current = tonumber(redis.call('get', key) or "0") if current + 1 > limit then 
return 0 else redis.call("INCRBY", key,"1") redis.call("expire", key,"2") return current + 1 end

4、自定義限流注解

import java.lang.annotation.*;

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisRateLimiter {

   //往令牌桶放入令牌的速率
    double value() default  Double.MAX_VALUE;
    //獲取令牌的超時(shí)時(shí)間
    double limit() default  Double.MAX_VALUE;
}

5、自定義切面類(lèi) RedisLimiterAspect 類(lèi) ,修改掃描自己controller類(lèi)

import com.imooc.annotation.RedisRateLimiter;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.assertj.core.util.Lists;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.List;

@Aspect
@Component
public class RedisLimiterAspect {
    @Autowired
    private HttpServletResponse response;

    /**
     * 注入redis操作類(lèi)
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

     private DefaultRedisScript<List> redisScript;

    /**
     * 初始化 redisScript 類(lèi)
     * 返回值為 List
     */
    @PostConstruct
    public void init(){
        redisScript = new DefaultRedisScript<List>();
        redisScript.setResultType(List.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("limit.lua")));
    }

    public final static Logger log = LoggerFactory.getLogger(RedisLimiterAspect.class);

    @Pointcut("execution( public * com.zz.controller.*.*(..))")
    public void pointcut(){

    }
    @Around("pointcut()")
    public Object process(ProceedingJoinPoint proceedingJoinPoint) throws  Throwable {
        MethodSignature  signature = (MethodSignature)proceedingJoinPoint.getSignature();
        //使用Java 反射技術(shù)獲取方法上是否有@RedisRateLimiter 注解類(lèi)
        RedisRateLimiter redisRateLimiter = signature.getMethod().getDeclaredAnnotation(RedisRateLimiter.class);
        if(redisRateLimiter == null){
            //正常執(zhí)行方法,執(zhí)行正常業(yè)務(wù)邏輯
            return proceedingJoinPoint.proceed();
        }
        //獲取注解上的參數(shù),獲取配置的速率
        double value = redisRateLimiter.value();
        double time = redisRateLimiter.limit();


        //list設(shè)置lua的keys[1]
        //取當(dāng)前時(shí)間戳到單位秒
        String key = "ip:"+ System.currentTimeMillis() / 1000;

        List<String> keyList = Lists.newArrayList(key);

        //用戶Mpa設(shè)置Lua 的ARGV[1]
        //List<String> argList = Lists.newArrayList(String.valueOf(value));

        //調(diào)用腳本并執(zhí)行
        List result = stringRedisTemplate.execute(redisScript, keyList, String.valueOf(value),String.valueOf(time));

        log.info("限流時(shí)間段內(nèi)訪問(wèn)第:{} 次", result.toString());

        //lua 腳本返回 "0" 表示超出流量大小,返回1表示沒(méi)有超出流量大小
        if(StringUtils.equals(result.get(0).toString(),"0")){
            //服務(wù)降級(jí)
            fullback();
            return null;
        }

        // 沒(méi)有限流,直接放行
        return proceedingJoinPoint.proceed();
    }

    /**
     * 服務(wù)降級(jí)方法
     */
    private  void  fullback(){
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter writer = null;
        try {
            writer= response.getWriter();
            JSONObject o = new JSONObject();
            o.put("status",500);
            o.put("msg","Redis限流:請(qǐng)求太頻繁,請(qǐng)稍后重試!");
            o.put("data",null);
            writer.printf(o.toString()
            );

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(writer != null){
                writer.close();
            }
        }
    }
}

6、在需要限流的類(lèi)添加注解

import com.imooc.annotation.RedisRateLimiter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@Api(value = "限流", tags = {"限流測(cè)試接口"})
@RequestMapping("limiter")
public class LimiterController {

    @ApiOperation(value = "Redis限流注解測(cè)試接口",notes = "Redis限流注解測(cè)試接口", httpMethod = "GET")
    @RedisRateLimiter(value = 10, limit = 1)
    @GetMapping("/redislimit")
    public IMOOCJSONResult redislimit(){

        System.out.println("Redis限流注解測(cè)試接口");
        return IMOOCJSONResult.ok();
    }


}

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

相關(guān)文章

  • 同一份數(shù)據(jù)Redis為什么要存兩次

    同一份數(shù)據(jù)Redis為什么要存兩次

    這篇文章主要介紹了同一份數(shù)據(jù)Redis為什么要存兩次,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave)

    Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave)

    這篇文章主要介紹了Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • redis2.8配置文件中文翻譯版

    redis2.8配置文件中文翻譯版

    這篇文章主要介紹了redis2.8配置文件中文翻譯版,本文翻譯了配置文件中的參數(shù)說(shuō)明,非常詳細(xì),需要的朋友可以參考下
    2015-06-06
  • Redis做預(yù)定庫(kù)存緩存功能設(shè)計(jì)使用

    Redis做預(yù)定庫(kù)存緩存功能設(shè)計(jì)使用

    這篇文章主要為大家介紹了Redis做預(yù)定庫(kù)存緩存功能設(shè)計(jì)使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • spring?boot集成redis基礎(chǔ)入門(mén)實(shí)例詳解

    spring?boot集成redis基礎(chǔ)入門(mén)實(shí)例詳解

    redis在spring?boot項(xiàng)目開(kāi)發(fā)中是常用的緩存套件,常見(jiàn)使用的是spring-boot-starter-data-redis,這篇文章主要介紹了spring?boot集成redis基礎(chǔ)入門(mén),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • 淺談Redis?中的過(guò)期刪除策略和內(nèi)存淘汰機(jī)制

    淺談Redis?中的過(guò)期刪除策略和內(nèi)存淘汰機(jī)制

    本文主要介紹了Redis?中的過(guò)期刪除策略和內(nèi)存淘汰機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Redis Cluster的圖文講解

    Redis Cluster的圖文講解

    今天小編就為大家分享一篇關(guān)于Redis Cluster的圖文講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Redis簡(jiǎn)單動(dòng)態(tài)字符串SDS的實(shí)現(xiàn)示例

    Redis簡(jiǎn)單動(dòng)態(tài)字符串SDS的實(shí)現(xiàn)示例

    Redis沒(méi)有直接復(fù)用C語(yǔ)言的字符串,而是新建了SDS,本文主要介紹了Redis簡(jiǎn)單動(dòng)態(tài)字符串SDS的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • Redis中Bloom filter布隆過(guò)濾器的學(xué)習(xí)

    Redis中Bloom filter布隆過(guò)濾器的學(xué)習(xí)

    布隆過(guò)濾器是一個(gè)非常長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)哈希函數(shù)的組合,可用于檢索一個(gè)元素是否存在,本文就詳細(xì)的介紹一下Bloom filter布隆過(guò)濾器,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-12-12
  • win 7 安裝redis服務(wù)【筆記】

    win 7 安裝redis服務(wù)【筆記】

    Redis是一個(gè)開(kāi)源的使用ANSI C語(yǔ)言編寫(xiě)、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的API。
    2016-05-05

最新評(píng)論