美文网首页
实现一个简单的限流器

实现一个简单的限流器

作者: 猫螺丝股记 | 来源:发表于2023-05-11 14:38 被阅读0次
/**
 * 限流器初始化
 * 
 **/
@Component
public class RateLimiterInitializer implements InitializingBean {
    @Resource
    private ApplicationContext applicationContext;

    @Override
    public void afterPropertiesSet() {
        Map<String, Object> map = applicationContext.getBeansWithAnnotation(UseLimiter.class);
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object val = entry.getValue();
            Class<?> clazz = AopUtils.getTargetClass(val);
            Method[] methods = clazz.getMethods();
            for (Method m : methods) {
                if (!m.isAnnotationPresent(Limiter.class)) {
                    continue;
                }

                StringBuilder params = new StringBuilder();
                params.append(m.getName()).append(";");
                for (Type type : m.getGenericParameterTypes()) {
                    params.append(type.getTypeName()).append(";");
                }
                params.append(m.getAnnotatedReturnType().getType());
                Limiter limiter = m.getAnnotation(Limiter.class);
                RateLimitContextHolder.put(params.toString(), limiter.permits());
            }

        }

    }

}

```java
//  aop处理

/**
 * <h2>限流处理</h2>
 * <pre>
 *     当相应的参数大于0则进入到相应的处理流程中;
 *   
 * </pre>
 **/
@Component
@Aspect
public class RateLimitAspect {

   // 拦截方法上的@Limiter
    @Pointcut("@annotation(.Limiter)")
    public void point() {
        //
    }

    @Around("point()")
    public Object limit(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        Limiter limit = methodSignature.getMethod().getDeclaredAnnotation(Limiter.class);
        if (limit.timeout() > 0) {
            return circuitBreaker(proceedingJoinPoint, limit.timeout());
        } else if (limit.permits() > 0) {
            StringBuilder key = new StringBuilder();
            key.append(methodSignature.getMethod().getName()).append(";");
            for (Type type : methodSignature.getMethod().getGenericParameterTypes()) {
                key.append(type.getTypeName()).append(";");
            }
            key.append(methodSignature.getMethod().getAnnotatedReturnType().getType());

            Semaphore limiter = RateLimitContextHolder.get(key.toString());
            try {
                log.info("限流执行中,剩余可用令牌数:{}, 参数:{}, 方法:{}",
                        limiter == null ? "empty" : limiter.availablePermits(), key, methodSignature.getMethod());

                if (limiter != null && !limiter.tryAcquire()) {
                    throw new BizException("请求频率超过限制,请稍后再试!");
                }
                return proceedingJoinPoint.proceed();
            } finally {
                // 释放
                if(limiter != null){
                    limiter.release();
                }
            }

        }
        return null;
    }


    /**
     * 熔断器
     *
     * @param proceedingJoinPoint point
     * @param timeout             timeout
     * @return 处理结果
     */
    private Object circuitBreaker(ProceedingJoinPoint proceedingJoinPoint, int timeout) {
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<Object> future = es.submit(() -> {
            try {
                return proceedingJoinPoint.proceed();
            } catch (Throwable throwable) {
                throw new BizException("处理异常,请稍后再试!");
            }
        });

        final Object obj;
        try {
            obj = future.get(timeout, TimeUnit.MILLISECONDS);
            return obj;
        } catch (Throwable e) {
            future.cancel(true);
            throw new BizException("处理异常,请稍后再试!");
        }
    }

}





相关文章

  • 限流器的简单实现

    问题分析 场景 场景如下:我们有10w台设备,这10w台设备会不定时向服务端上报数据,如果消息的并发量比较大的话,...

  • 基于计数器的服务接口限流实例

    计数器限流是服务接口限流策略中最为基本和简单的方式。本实例将实现不同接口设置不同的限流方案。 首先我们需要需要定义...

  • 经典限流算法:令牌桶算法

    Guava 的限流器使用上还是很简单的,那它是如何实现的呢?Guava 采用的是令牌桶算法,其核心是要想通过限流器...

  • 限流算法实现

    并发数限流 1. 计数器并发数限流 2. 信号量(Semaphore) 其实最简单的方法就是用信号量来实现: QP...

  • 限流降级方案

    限流算法 并发数限流 计数器并发数限流:使用共享变量实现 信号量:使用java中的Semaphore QPS限流 ...

  • Guava RateLimiter的实现

    限流 高并发系统有三大利器:缓存 、限流 、降级。对于限流的实现,有多种算法:计数器,漏桶法,令牌桶法。计数器法无...

  • SpringBoot基于RateLimiter+AOP动态的为不

    一 限流实现: RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根...

  • 基于令牌桶算法的Java限流实现

    项目需要使用限流措施,查阅后主要使用令牌桶算法实现,为了更灵活的实现限流,就自己实现了一个简单的基于令牌桶算法的限...

  • 限流器

    如果是简单做一个限流器的话,利用zset也可以实现,以score作为时间戳,然后的话,value为任意(保证不重复...

  • 高可用实践-限流算法

    限流算法 常见的限流算法有计数器算法、漏桶算法和令牌桶算法。 计数器法 计数器算法“简单粗暴”。该算法会维护一个c...

网友评论

      本文标题:实现一个简单的限流器

      本文链接:https://www.haomeiwen.com/subject/whussdtx.html