【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务

简介: 随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。

限流器的算法选项

随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。

Java是一种非常流行的编程语言,具有广泛的应用场景。在Java中,实现限流器的方法有很多种。本文将介绍一些常见的实现方法和技术。

令牌桶算法

令牌桶算法是一种常见的限流算法,它基于一个令牌桶来控制请求的速率。在令牌桶算法中,令牌桶以固定的速率生成令牌,并将这些令牌存储在桶中。每当一个请求到达时,它必须从桶中获取一个令牌才能被处理。如果桶中没有足够的令牌,请求将被拒绝。

在Java中,可以使用Guava库中的RateLimiter类来实现令牌桶算法。RateLimiter类提供了一种简单而有效的方式来控制请求的速率。

接下来我们开发带着大家手把手去实现一个属于我们自己的限流器服务组件。

开发阶段

Maven的依赖配置

首先,我们需要开始配置Maven所具有的依赖关系,主要包含者基础的工具类配置信息包含了Hutools和apache-commons相关的
基础工具组件,以及针对于我们的限流器的服务库Guava。

   <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
           <dependency>
            <groupId>com.fengwenyi</groupId>
            <artifactId>JavaLib</artifactId>
            <version>2.1.6</version>
        </dependency>        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
        <!--joda-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0-jre</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.8</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
         <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>        
    </dependencies>

核心服务类之间的关系

主要包含了各个服务类之间的关系,包含了继承关系以及服务功能的继承总览机制。
在这里插入图片描述

定义限流器基础接口

首先,我们先定义一下我们的基础接口-ExecuteRateLimiter。

@FunctionalInterface
public interface ExecuteRateLimiter<P,R>{

    /**
     * 执行操作
     * @param param
     * @return
     */
    R execute(P param);
}

这个各类主要代表限流器的执行操作方法。

定义限流器工厂方法

接下来,我们定义一下限流器工厂方法类ExecuteRateLimiterFactory。主要目的作为我们限流器的创建限流器的功能。

@FunctionalInterface
public interface ExecuteRateLimiterFactory<P,R> {
    R create(P param);
}

主要目的作为创建限流器ExecuteRateLimiter接口,接下来我们会进行覆盖和实现改接口进行构建不同厂商的限流器服务实现类。


Guava厂商的限流器所需要的参数类 — GuavaRateLimiterParam

在此,我们主要去实现我们 的限流器的参数实现类:GuavaRateLimiterParam。

@Builder
@Data
public class GuavaRateLimiterParam {

    private int permitsPerSecond;

    private int warmupPeriod;
 
    private TimeUnit timeUnit;
}

主要去属于封装了对应的Guava限流器的参数属性:

  • permitsPerSecond: 返回的RateLimiter的速率,意味着每秒有多少个许可变成有效。
  • warmupPeriod: 在这段时间内RateLimiter会增加它的速率,在抵达它的稳定速率或者最大速率之前
  • timeUnit:参数warmupPeriod 的时间单位

Guava厂商的限流器工厂类 — GuavaExecuteRateLimiterFactory

首先,我们需要进行实现属于我们Guava厂商的限流器的工厂类,主要目的是去实现对应的Guava的限流器的核心类:RateLimiter,并且作为我们Spring容器的一个组件进行注册到容器中去。

@Component
public class GuavaExecuteRateLimiterFactory implements ExecuteRateLimiterFactory<GuavaRateLimiterParam,RateLimiter> {

    /**
     * 创建RateLimiter对象
     * @param param
     * @return
     */
    @Override
    public RateLimiter create(GuavaRateLimiterParam param) {
        return RateLimiter.create(param.getPermitsPerSecond(),param.getWarmupPeriod(),param.getTimeUnit());
    }
}

实现面向切面模式的限流器实现功能

  • 限流器注解
  • 限流器切面

限流器注解

限流器的注解,主要面向于限流器的功能的参数包装,方便开发者可以再注解上进行定义不同的参数选项,基本等价于我们的GuavaRateLimiterParam的属性参数。可见:

@java.lang.annotation.Target({ElementType.METHOD,ElementType.FIELD})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
@Component
@Autowired(required = false)
public @interface GuavaExecuteRateLimiter {

    /**
     * 返回的RateLimiter的速率,意味着每秒有多少个许可变成有效。
     */
    int permitsPerSecond() default 500;

    /**
     * 在这段时间内RateLimiter会增加它的速率,在抵达它的稳定速率或者最大速率之前
     */
    int warmupPeriod() default 5;

    /**
     * 参数warmupPeriod 的时间单位
     */
    TimeUnit timeUnit() default TimeUnit.SECONDS;

}

限流器切面

主要针对于限流器的切面类进行控制处理-GuavaExecuteRateLimterAspect类。

@Slf4j
@Aspect
@Component
public class GuavaExecuteRateLimterAspect {
    @Pointcut("@annotation(com.hyts.assemble.ratelimiter.guava.anno.GuavaExecuteRateLimiter)")
    public void methodPointCut() {}


    @Autowired
    GuavaExecuteRateLimiterFactory executeRateLimiterFactory;


    ConcurrentHashMap<String, RateLimiter> rateLimiterConcurrentHashMap = new ConcurrentHashMap<>();



    Joiner joiner = Joiner.on("-").skipNulls();



    @Around("methodPointCut()")
    public Object doMethod(ProceedingJoinPoint proceedingJoinPoint){
        MethodSignature methodSignature = (MethodSignature)proceedingJoinPoint.getSignature();
        Method method = methodSignature.getMethod();
        GuavaExecuteRateLimiter guavaExecuteRateLimiter = method.getAnnotation(GuavaExecuteRateLimiter.class);
        GuavaRateLimiterParam guavaRateLimiterParam = GuavaRateLimiterParam.builder().
                permitsPerSecond(guavaExecuteRateLimiter.permitsPerSecond()).
                timeUnit(guavaExecuteRateLimiter.timeUnit()).
                warmupPeriod(guavaExecuteRateLimiter.warmupPeriod()).build();
        String key = joiner.join(guavaExecuteRateLimiter.permitsPerSecond(),
                guavaExecuteRateLimiter.timeUnit().toString()
                ,guavaExecuteRateLimiter.warmupPeriod());
        RateLimiter rateLimiter = rateLimiterConcurrentHashMap.
                computeIfAbsent(key,param-> executeRateLimiterFactory.create(guavaRateLimiterParam));
        try {
            double rateValue = rateLimiter.acquire();
            log.info("执行限流方法操作处理:当前qps:{} delay rate limiter value:{}",guavaExecuteRateLimiter.permitsPerSecond(),rateValue);
            return proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        } catch (Throwable e) {
            log.error("执行限流控制方法失败!",e);
            return null;
        }
    }
}

主要用于通过AOP进行实时构建GuavaExecuteRateLimiterFactory进行构建和创建对应的RateLimiter对象,并且缓存到对应的容器里面进行构建。
进行执行限流操纵控制。

相关文章
|
9天前
|
存储 数据采集 监控
信息系统架构开发方法ADM
信息系统架构开发方法ADM
37 5
|
19天前
|
监控 负载均衡 Cloud Native
ZooKeeper分布式协调服务详解:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入剖析ZooKeeper分布式协调服务原理,涵盖核心概念如Server、Client、ZNode、ACL、Watcher,以及ZAB协议在一致性、会话管理、Leader选举中的作用。讨论ZooKeeper数据模型、操作、会话管理、集群部署与管理、性能调优和监控。同时,文章探讨了ZooKeeper在分布式锁、队列、服务注册与发现等场景的应用,并在面试方面分析了与其它服务的区别、实战挑战及解决方案。附带Java客户端实现分布式锁的代码示例,助力提升面试表现。
32 2
|
23天前
|
API 数据库 开发者
构建高效可靠的微服务架构:后端开发的新范式
【4月更文挑战第8天】 随着现代软件开发的复杂性日益增加,传统的单体应用架构面临着可扩展性、维护性和敏捷性的挑战。为了解决这些问题,微服务架构应运而生,并迅速成为后端开发领域的一股清流。本文将深入探讨微服务架构的设计原则、实施策略及其带来的优势与挑战,为后端开发者提供一种全新视角,以实现更加灵活、高效和稳定的系统构建。
23 0
|
9天前
|
存储 开发框架 前端开发
前端框架EXT.NET Dotnet 3.5开发的实验室信息管理系统(LIMS)成品源码 B/S架构
发展历史:实验室信息管理系统(LIMS),就是指通过计算机网络技术对实验的各种信息进行管理的计算机软、硬件系统。也就是将计算机网络技术与现代的管理思想有机结合,利用数据处理技术、海量数据存储技术、宽带传输网络技术、自动化仪器分析技术,来对实验室的信息管理和质量控制等进行全方位管理的计算机软、硬件系统,以满足实验室管理上的各种目标(计划、控制、执行)。
|
11天前
|
消息中间件 监控 持续交付
构建高效微服务架构:后端开发的进阶之路
【4月更文挑战第20天】 随着现代软件开发的复杂性日益增加,传统的单体应用已难以满足快速迭代和灵活部署的需求。微服务架构作为一种新兴的分布式系统设计方式,以其独立部署、易于扩展和维护的特点,成为解决这一问题的关键。本文将深入探讨微服务的核心概念、设计原则以及在后端开发实践中如何构建一个高效的微服务架构。我们将从服务划分、通信机制、数据一致性、服务发现与注册等方面入手,提供一系列实用的策略和建议,帮助开发者优化后端系统的性能和可维护性。
|
10天前
|
存储 关系型数据库 分布式数据库
电子好书发您分享《PolarDB分布式版架构介绍PolarDB分布式版架构介绍》
**《PolarDB分布式版架构介绍》电子书分享:** 探索阿里云PolarDB分布式设计,采用计算存储分离,借助GMS、CN组件实现大规模扩展。[阅读更多](https://developer.aliyun.com/ebook/8332/116553?spm=a2c6h.26392459.ebook-detail.5.3b3b2ccbVVjjt0)
15 3
|
2天前
|
安全 Java 开发者
构建高效微服务架构:后端开发的新范式Java中的多线程并发编程实践
【4月更文挑战第29天】在数字化转型的浪潮中,微服务架构已成为软件开发的一大趋势。它通过解耦复杂系统、提升可伸缩性和促进敏捷开发来满足现代企业不断变化的业务需求。本文将深入探讨微服务的核心概念、设计原则以及如何利用最新的后端技术栈构建和部署高效的微服务架构。我们将分析微服务带来的挑战,包括服务治理、数据一致性和网络延迟问题,并讨论相应的解决方案。通过实际案例分析和最佳实践的分享,旨在为后端开发者提供一套实施微服务的全面指导。 【4月更文挑战第29天】在现代软件开发中,多线程技术是提高程序性能和响应能力的重要手段。本文通过介绍Java语言的多线程机制,探讨了如何有效地实现线程同步和通信,以及如
|
6天前
使用JWT的服务分布式部署之后报错:JWT Check Failure:
使用JWT的服务分布式部署之后报错:JWT Check Failure:
16 1
|
7天前
|
持续交付 API 开发者
构建高效微服务架构:后端开发的新范式
【4月更文挑战第24天】 随着现代软件系统的复杂性日益增加,传统的单体应用已难以满足快速迭代与灵活扩展的需求。微服务架构作为一种新兴的软件开发模式,以其服务的细粒度、独立部署和弹性伸缩等优势,正在逐渐成为后端开发的重要趋势。本文将深入探讨微服务架构的设计原则、关键技术以及在实际业务中的应用实践,旨在为后端开发者提供构建和维护高效微服务架构的参考指南。
|
8天前
|
关系型数据库 分布式数据库 数据库
电子好书发您分享《PolarDB分布式版架构介绍》
阅读阿里云电子书《PolarDB分布式版架构介绍》,深入理解这款高性能数据库的分布式架构设计。书中通过图文并茂的方式揭示了PolarDB在分布式场景下的核心特性和技术优势,适合数据库爱好者和云计算从业者学习。[阅读链接](https://developer.aliyun.com/ebook/8332/116553?spm=a2c6h.26392459.ebook-detail.5.4ab72ccbIzDq2Q)