返回顶部
首页 > 资讯 > 后端开发 > Python >Java Redisson多策略注解限流
  • 767
分享到

Java Redisson多策略注解限流

2024-04-02 19:04:59 767人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录前言自定义注解定义限流类型生成key的工具类定义aop具体逻辑前言 限流:使用Redisson的RRateLimiter进行限流多策略:map+函数式接口优化if判断 限流:使用

前言

限流:使用Redisson的RRateLimiter进行限流多策略:map+函数式接口优化if判断

限流:使用Redisson的RRateLimiter进行限流

多策略:map+函数式接口优化if判断

自定义注解


@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface RedisLimit {


    String prefix() default "rateLimit:";

    //限流唯一标示
    String key() default "";

    //限流单位时间(单位为s)
    int time() default 1;

    //单位时间内限制的访问次数
    int count();

    //限流类型
    LimitType type() default LimitType.CUSTOM;

}

定义限流类型

public enum LimitType {

    
    CUSTOM,

    
    IP,

    
    METHOD,

    
    PARAMS,

    
    USER,

    
    REQUEST_URI,

    
    REQUESTURI_USERID,


    
    SINGLEUSER,

    
    SINGLEMETHOD,

    
    REQUEST_URI_PARAMS,

    
    REQUEST_URI_PARAMS_USERID;
    
}

生成key的工具类

根据类型生成的对象(key)的工具类,使用map+函数式接口优化if,其中BaseContext是一个获取用户唯一标识userId的工具类

@Component
public class ProceedingJoinPointUtil {
    @Autowired
    private httpservletRequest request;

    private Map<LimitType, Function<ProceedingJoinPoint,String>> functionMap = new HashMap<>(9);

    @PostConstruct
    void initMap(){
        //初始化策略
        functionMap.put(LimitType.METHOD, this::getMethodTypeKey);
        functionMap.put(LimitType.PARAMS, this::getParamsTypeKey);
        functionMap.put(LimitType.USER, this::getUserTypeKey);
        functionMap.put(LimitType.REQUEST_URI,proceedingJoinPoint ->
                request.getRequestURI());
        functionMap.put(LimitType.REQUESTURI_USERID, proceedingJoinPoint ->
                request.getRequestURI()+BaseContext.getUserId());
        functionMap.put(LimitType.REQUEST_URI_PARAMS,proceedingJoinPoint ->
                request.getRequestURI()+getParams(proceedingJoinPoint));
        functionMap.put(LimitType.REQUEST_URI_PARAMS_USERID,proceedingJoinPoint ->
                request.getRequestURI()+getParams(proceedingJoinPoint)+BaseContext.getUserId());
        functionMap.put(LimitType.SINGLEUSER,(proceedingJoinPoint)->
                String.valueOf(BaseContext.getUserId()));
        functionMap.put(LimitType.SINGLEMETHOD,(proceedingJoinPoint -> {
            StringBuilder sb = new StringBuilder();
            appendMthodName(proceedingJoinPoint,sb);
            return sb.toString();
        }));
    }

    public Object geTKEy(ProceedingJoinPoint joinPoint, RedisLimit redisLimit) {
        //根据限制类型生成key
        Object generateKey = "";
        //自定义
        if(redisLimit.type() != LimitType.CUSTOM){
            generateKey = generateKey(redisLimit.type(), joinPoint);
        }else {
            //非自定义
            generateKey = redisLimit.key();
        }
        return generateKey;
    }

    
    private Object generateKey(LimitType type , ProceedingJoinPoint joinPoint) {
        Function function = functionMap.get(type);
        Object result = function.apply(joinPoint);
        return result;
    }

    
    private String getMethodTypeKey(ProceedingJoinPoint joinPoint){
        StringBuilder sb = new StringBuilder();
        appendMthodName(joinPoint, sb);
        return sb.toString();
    }



    
    private String getParamsTypeKey(ProceedingJoinPoint joinPoint){
        StringBuilder sb = new StringBuilder();
        appendMthodName(joinPoint, sb);
        appendParams(joinPoint, sb);
        return sb.toString();
    }



    
    private String getUserTypeKey(ProceedingJoinPoint joinPoint){
        StringBuilder sb = new StringBuilder();
        appendMthodName(joinPoint, sb);
        appendParams(joinPoint, sb);
        //获取userId
        appendUserId(sb);
        return sb.toString();
    }


    
    private void appendMthodName(ProceedingJoinPoint joinPoint, StringBuilder sb) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        sb.append(joinPoint.getTarget().getClass().getName())//类名
                .append(method.getName());//方法名
    }

    
    private void appendParams(ProceedingJoinPoint joinPoint, StringBuilder sb) {
        for (Object o : joinPoint.getArgs()) {
            sb.append(o.toString());
        }
    }
    private String getParams(ProceedingJoinPoint joinPoint) {
        StringBuilder sb = new StringBuilder();
        for (Object o : joinPoint.getArgs()) {
            if(o instanceof MultipartFile){
                try {
                    ImageTypeCheck.getImgHeightAndWidth(((MultipartFile) o).getInputStream());
                } catch (IOException e) {
                    throw new BusinessException("MultipartFile输入流获取失败,source:ProceedingJoinPointUtils.149",USER_PRINCIPAL_EMaiL);
                }
            }else {
                sb.append(o.toString());
            }
        }
        return sb.toString();
    }

    
    private void appendUserId(StringBuilder sb) {
        sb.append(BaseContext.getUserId());
    }
}

定义aop具体逻辑

@Aspect
@Component
@Slf4j
public class RedisLimitAspect {
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ProceedingJoinPointUtil proceedingJoinPointUtil;

    @Pointcut("@annotation(com.cat.www.aop.limit.anno.RedisLimit)")
    private void pointCut() {
    }

    @Around("pointCut() && @annotation(redisLimit)")
    private Object around(ProceedingJoinPoint joinPoint, RedisLimit redisLimit) {
        Object generateKey = proceedingJoinPointUtil.getKey(joinPoint, redisLimit);
        //redis key
        String key = redisLimit.prefix() +generateKey.toString();
        //声明一个限流器
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);

        //设置速率,time秒中产生count个令牌
        rateLimiter.trySetRate(RateType.OVERALL, redisLimit.count(), redisLimit.time(), RateIntervalUnit.SECONDS);

        // 试图获取一个令牌,获取到返回true
        boolean tryAcquire = rateLimiter.tryAcquire();
        if (!tryAcquire) {
            return new ResultData<>().FAILED().setResultIns("访问过于频繁");
        }
        Object obj = null;
        try {
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException();
        }

        return obj;
    }
}

到此这篇关于Java Redisson多策略注解限流的文章就介绍到这了,更多相关Java Redisson内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java Redisson多策略注解限流

本文链接: https://lsjlt.com/news/168189.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java Redisson多策略注解限流
    目录前言自定义注解定义限流类型生成key的工具类定义aop具体逻辑前言 限流:使用Redisson的RRateLimiter进行限流多策略:map+函数式接口优化if判断 限流:使用...
    99+
    2024-04-02
  • SpringCloudHystrix服务降级限流策略详解
    目录前言Hystrix简介Hystrix的使用服务降级system服务控制层System2调System降级场景服务熔断总结前言 前面说到在我们应对高并发的场景,请求量过于大的情况...
    99+
    2023-01-04
    Spring Cloud Hystrix 服务降级限流 Spring Cloud Hystrix
  • Redis中如何实现限流策略
    这篇文章将为大家详细讲解有关Redis中如何实现限流策略,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、简单的限流基本原理当系统处理能力有限,如何组织计划外的请求对系统...
    99+
    2024-04-02
  • redisson分布式限流RRateLimiter源码解析
    目录分布式限流-单位时间多实例多线程访问次数限制1.简单使用2. 实现限流redisson使用了哪些redis数据结构3. 超过10s,我再次获取一个令牌,数据结构发生的变化4. 源...
    99+
    2022-11-13
    redisson分布式限流RRateLimiter redisson RRateLimiter
  • redis实现的四种常见限流策略
    目录引言固定时间窗口算法实现滑动时间窗口算法实现漏桶算法实现令牌桶算法引言 在web开发中功能是基石,除了功能以外运维和防护就是重头菜了。因为在网站运行期间可能会因为突然的...
    99+
    2024-04-02
  • Nginx限流和黑名单配置的策略
    目录1 背景介绍2 Nginx 的限流策略2.1 limit_req_zone限制访问频率2.2 limit_conn_zone限制最大连接数3 黑名单设置1 背景介绍 为了防止一些...
    99+
    2024-04-02
  • Nginx限流与防DDoS攻击策略是什么
    Nginx是一款高性能的Web服务器和反向代理服务器,可以通过一些策略来限制流量并防止DDoS攻击。 限流策略:Nginx可以通...
    99+
    2024-05-06
    Nginx DDoS攻击
  • Redisson分布式限流的实现原理解析
    目录正文RRateLimiter使用RRateLimiter的实现RRateLimiter使用时注意事项RRateLimiter是非公平限流器Rate不要设置太大限流的上限取决于Redis单实例的性能分布式限流的本质正文...
    99+
    2023-02-12
    Redisson分布式限流 Redisson 分布式
  • 详解Java策略模式
    一、策略模式到底是什么? 策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端...
    99+
    2024-04-02
  • 详解基于redis实现的四种常见的限流策略
    目录一、引言二、固定时间窗口算法三、滑动时间窗口算法四、漏桶算法五、令牌桶算法一、引言 在web开发中功能是基石,除了功能以外运维和防护就是重头菜了。因为在网站运行期间可能...
    99+
    2024-04-02
  • Java多线程(3)---锁策略、CAS和JUC
    目录 前言 一.锁策略 1.1乐观锁和悲观锁 ⭐ 两者的概念 ⭐实现方法 1.2读写锁  ⭐概念 ⭐实现方法 1.3重量级锁和轻量级锁 1.4自旋锁和挂起等待锁 ⭐概念 ⭐代码实现 1.5公平锁和非公平锁 1.6可重入锁和不可重入锁 二.C...
    99+
    2023-08-31
    开发语言 多线程 java-ee
  • 详解Java ThreadPoolExecutor的拒绝策略
    目录背景线程池基本原理线程池拒绝策略AbortPolicyCallerRunsPolicyDiscardPolicy示例执行结果DiscardOldestPolicy示例说明自定义拒...
    99+
    2024-04-02
  • Java JVM编译策略案例详解
    解释器 当虚拟机启动时,解释器可以首先发挥作用,而不必等待编译器全部编译完成再执行,这样可以省去许多不必要的编译时间。并且随着程序运行时间的推移,编译器逐渐发挥作用,根据热点探测功能...
    99+
    2024-04-02
  • dubbo负载均衡策略(XML、注解、SpringBoot配置)
    在Dubbo中,可以通过XML配置、注解和Spring Boot配置来配置负载均衡策略。1. XML配置:在XML配置文件中,可以使...
    99+
    2023-09-20
    dubbo
  • Java设计模式之java策略模式详解
    目录为什么使用策略模式?策略模式包含角色策略模式的类图排序案例策略模式的优点策略模式的缺点适用场景源码分析策略模式的典型应用Java Comparator 中的策略模式参考文...
    99+
    2024-04-02
  • java设计模式--策略模式详解
    目录策略模式Demo代码:总结策略模式 策略模式(Strategy Pattern)属于行为型模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。用算法族分别封装起来...
    99+
    2024-04-02
  • JPA 注解及主键生成策略使用指南
    JPA 注解 Entity 常用注解 参考:JPA & Spring Data JPA学习与使用小记 指定对象与数据库字段映射时注解的位置:如@Id、@Column等注解指定Entity的字段与数据库字段对应关系时,注解的位置可以在Fiel...
    99+
    2023-08-16
    java jpa spring data jpa
  • 解析Java多线程之常见锁策略与CAS中的ABA问题
    目录1.常见的锁策略1.1乐观锁与悲观锁1.2读写锁与普通互斥锁1.3重量级锁与轻量级锁1.4挂起等待锁与自旋锁1.5公平锁与非公平锁1.6可重入锁与不可重入锁1.7死锁问题1.7....
    99+
    2024-04-02
  • Java JSP 可扩展性策略:处理高流量和复杂性
    水平扩展: 水平扩展是一种通过增加服务器数量来提高容量的策略。对于 JSP 应用程序,可以部署集群,其中多个服务器协同工作以处理请求。这种方法可以轻松扩展,以满足不断增加的流量需求。 负载均衡: 负载均衡器负责将请求分配到服务器集群中的各...
    99+
    2024-03-15
    JSP
  • Laravel 角色和权限:拦截器(Gates)和策略(Policies)解释
    在 Laravel 中,角色和权限多年来一直是最令人困惑的话题之一。大多数情况下,因为没有关于这些内容的文档:在框架中这类概念被用其他术语表述取代了,以至于我们没法简单的去理解这些内容。像这种概念术语有:「Gates(门面/拦截器)」、「P...
    99+
    2022-05-31
    laravel Gates 拦截器 laravel laravel论坛 laravel社区 laravel教程 laravel视频 laravel开源 laravel新手 laravel5
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作