All Projects → tangaiyun → redislimiter-spring-boot

tangaiyun / redislimiter-spring-boot

Licence: Apache-2.0 license
an excellent API limiting framework for Spring boot/cloud application, especially for microservice project

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to redislimiter-spring-boot

sample-spring-cloud-gateway
sample spring cloud application with embedded api gateway on spring cloud gateway with or without service discovery with eureka
Stars: ✭ 25 (-60.94%)
Mutual labels:  spring-cloud, rate-limiter
Api Boot
“ ApiBoot”是为接口服务而生的,基于“ SpringBoot”完成扩展和自动配置,内部封装了一系列的开箱即用Starters。
Stars: ✭ 460 (+618.75%)
Mutual labels:  spring-cloud, rate-limiter
Limiter
一个注解使你的SpringBoot项目获得分布式锁和限流器能力
Stars: ✭ 93 (+45.31%)
Mutual labels:  spring-cloud, rate-limiter
Advanced Java
😮 Core Interview Questions & Answers For Experienced Java(Backend) Developers | 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识
Stars: ✭ 59,142 (+92309.38%)
Mutual labels:  spring-cloud
nestjs-ratelimiter
Distributed consistent flexible NestJS rate limiter based on Redis
Stars: ✭ 49 (-23.44%)
Mutual labels:  rate-limiter
zlimiter
A toolkit for rate limite,support memory and redis
Stars: ✭ 17 (-73.44%)
Mutual labels:  rate-limiter
easemesh
A service mesh implementation for connecting, control, and observe services in spring-cloud.
Stars: ✭ 454 (+609.38%)
Mutual labels:  spring-cloud
Springcloud
springCloud学习
Stars: ✭ 251 (+292.19%)
Mutual labels:  spring-cloud
gentle-force
Brute-force, error and request rate limiting
Stars: ✭ 45 (-29.69%)
Mutual labels:  rate-limiter
Spring5Tutorial
Spring 文件的範例資源
Stars: ✭ 36 (-43.75%)
Mutual labels:  spring-cloud
extension-springcloud
Axon Framework extension for Spring Cloud's Discovery mechanism integration to distribute Command messages.
Stars: ✭ 22 (-65.62%)
Mutual labels:  spring-cloud
flutter-chart-app
a chat app using flutter & dart & jpush
Stars: ✭ 51 (-20.31%)
Mutual labels:  spring-cloud
sparkzxl-framework
sparkzxl 基于spring boot的组件库
Stars: ✭ 20 (-68.75%)
Mutual labels:  spring-cloud
workshop-microservices
Treinamento voltado para arquitetos de software, líderes de equipe, desenvolvedores em geral...
Stars: ✭ 21 (-67.19%)
Mutual labels:  spring-cloud
spring-cloud-static
Static resources for the Spring Cloud website
Stars: ✭ 26 (-59.37%)
Mutual labels:  spring-cloud
Springcloudlearning
《史上最简单的Spring Cloud教程源码》
Stars: ✭ 16,218 (+25240.63%)
Mutual labels:  spring-cloud
spring-petclinic-cloud
Fork of the Spring Cloud Microservices project packaged to be deployed on several Cloud platforms: Kubernetes and Cloud Foundry
Stars: ✭ 106 (+65.63%)
Mutual labels:  spring-cloud
microservice workshop
Microservices Architecture Workshop focuses on helping the developers / architects to understand the key Architecture paradigms with hands on section. The course helps the developers from Monolithic App mindset to a Microservices based App development. It also helps the developers with hands on development experience with key Microservices infra…
Stars: ✭ 69 (+7.81%)
Mutual labels:  spring-cloud
diboot-cloud
diboot低代码开发平台微服务版
Stars: ✭ 37 (-42.19%)
Mutual labels:  spring-cloud
tech1-temple-java
Java Proofs of Concepts repository. No Longer Supported
Stars: ✭ 85 (+32.81%)
Mutual labels:  spring-cloud

English | 中文

redislimiter-spring-boot

An excellent API limiting framework for Spring boot/cloud application, especially for microservice project

Quickstart

Clone, build and install

git clone https://github.com/tangaiyun/redislimiter-spring-boot.git
cd redislimiter-spring-boot-starter
mvn clean install

Add to your POM

Then create a Spring boot API project refer to sample project "demo1",and you need to add dependency in pom.xml

        <dependency>
            <groupId>com.tay</groupId>
            <artifactId>redislimiter-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

Configuration

For resources/application.yml you need to add the following lines.

server:
    port: 8888                                #port
spring:
    application:
        name: demo1                           #application name must be set, otherwise the application can not start
    redis-limiter:                            #Limiter configuration
        redis-host: 127.0.0.1                 #redis server ip  
        check-action-timeout: 100             #check action will be executed asynchronous, this is the timeout value
        enable-dynamical-conf: true           #turn on the switch for dynammically limiting configuration support 

Create a RestController

package com.tay.demo1;

import com.tay.redislimiter.RateLimiter;
import com.tay.redislimiter.dynamic.DynamicRateLimiter;
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
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/test")
    //limiting based on userid, and an unique user can visit twice per one minute,userid was contained in the http header
    //RateLimiter annotation that means this configuration can not be change in runtime
    @RateLimiter(base = "#Headers['userid']", permits = 2, timeUnit = TimeUnit.MINUTES) 
    public String test() {
        return "test!";
    }

    @GetMapping("/dynamictest")
    //limiting based on user's IP, and an unique IP can visit five times per one minute, so 'X-Real-IP' is key of header for IP 
    //DynamicRateLimiter annotation that means this configuration can be changed dynamically in runime
    @DynamicRateLimiter(base = "#Headers['X-Real-IP']", permits = 5, timeUnit = TimeUnit.MINUTES)
    public String dynamicTest() {
        return "dynamictest!";
    }

}

Start Redis server

Start Redis server on a local machine or with Docker.

sudo docker run -d -p 6379:6379 redis

it is so crazy!

Run Demo1Application.java

Testing

You can use a HTTP client tool such as Postman, restd or curl, and get the URL http://localhost:8888/demo/test. Don't forget to add a pair value userid=tom in your HTTP request header. You will be able to find the user with userid "tom" can visit this url twice successfully at most in one minute.

With Postman/restd visiting http://localhost:8888/demo/dynamictest with the pair value X-Real-IP=127.0.0.1 in your HTTP request header, you can find only five requests with header X-Real-IP=127.0.0.1 will be successful in one minute.

Advanced Guide

Complete Configuration Items

spring:
    redis-limiter: 
        redis-host: 127.0.0.1           # redis server IP                   default:127.0.0.1
        redis-port: 6379                # redis service port                default:6379  
        redis-password: test            # redis password                    default:null 
        redis-connection-timeout: 2000  # redis connection timeout          default:2000
        redis-pool-max-idle: 50         # redis pool max idle               default: 50
        redis-pool-min-idle: 10         # redis pool mim idle               default:10 
        redis-pool-max-wait-millis: -1 # max wait time for get connection  default:-1 
        redis-pool-max-total: 200       # max total connection              default:200
        redis-key-prefix: #RL           # key prefix for visit footprint    default: #RL
        check-action-timeout: 100       # check action execution timeout    default: 100
        enable-dynamical-conf: true     # the switch for enable dynamical   default:false 
        channel: #RLConfigChannel      # conf change event pub/sub channel default: #RLConfigChannel   

Annotations

  • @RateLimiter
  • @DynamicRateLimiter

General Description

@RateLimiter @DynamicRateLimiter these two annotations have same four attributes (base, path, timeUnit, permits)

@Retention(RUNTIME)
@Target({ METHOD })
public @interface RateLimiter {

    String base() default "";

    String path() default "";

    TimeUnit timeUnit() default TimeUnit.SECONDS;

    int permits() default 10000;
}

@Retention(RUNTIME)
@Target({ METHOD })
public @interface DynamicRateLimiter {
    String base() default "";

    String path() default "";

    TimeUnit timeUnit() default TimeUnit.SECONDS;

    int permits() default 10000;
}

base (Spel expression)

Two annotations have the base attribute,that means what your limiting based on(maybe user's id, remote IP etc.). If you don't asssign base attribute, all requests will be accumulated as a whole one,the "base" should be a Spel exression。

@RateLimiter(base = "#Headers['userid']", permits = 2, timeUnit = TimeUnit.MINUTES) 
@DynamicRateLimiter(base = "#Headers['X-Real-IP']", permits = 5, timeUnit = TimeUnit.MINUTES)

At the present, the base expression only supports get value from HTTP header and cookie. In Spel expression evaluation context they are named as Headers and Cookies separately, so the two expressions are valid as below:


"#Headers['X-Real-IP']"
"#Cookies['userid']"

path

The path has default value "" if you did not set. When the path has value "", and the value of path will be set as request.getRequestURI(). In general, that is OK. But in one special case, you should need to set path explicitly.

For example:

    @GetMapping("/user/{userid}")
    @DynamicRateLimiter(base = "#Headers['X-Real-IP']", path = "/user", permits = 5, timeUnit = TimeUnit.MINUTES)
    public User get(@PathVariable String userid) {
        User user ...
       
        return user;
    }

The GetMapping has PathVariable-{userid}. In this case, we would not count visiting times base on /user/001. If we set the path value to /user, so all requsts like /user/xxx will be added up base on /user.

timeUnit

Four TimeUnits are valid:

  • TimeUnit.SECONDS
  • TimeUnit.MINUTES
  • TimeUnit.HOURS
  • TimeUnit.DAYS

permits

Number of visits allowed per unit of time

Dynamic configuration

@DynamicRateLimiter annotation makes configuration can be changed dynamically, we can change the configuraton by internal RESTful API.

RestController
@RequestMapping("/limiterconfig")
@RequiredArgsConstructor
public final class LimiterConfigResource implements InitializingBean, ApplicationContextAware {
    ...
    
    @PutMapping
    public void update(@RequestBody LimiterConfig limiterConfig, HttpServletResponse response) throws IOException {
        if(applicationName.equals(limiterConfig.getApplicationName())) {
            publish(limiterConfig);
        }
        else {
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            response.getWriter().print("Bad request for updating limiter configuration!");
        }
    }
    @GetMapping
    public LimiterConfig get(@RequestParam("controller") String controller, @RequestParam("method")String method) {
        String limiterConfigKey = controller + ":" + method;
        return redisLimiterConfigProcessor.get(limiterConfigKey);
    }

    @DeleteMapping
    public void delete(@RequestParam("controller") String controller, @RequestParam("method")String method) {
        LimiterConfig limiterConfig = new LimiterConfig();
        limiterConfig.setApplicationName(applicationName);
        limiterConfig.setControllerName(controller);
        limiterConfig.setMethodName(method);
        limiterConfig.setDeleted(true);
        publish(limiterConfig);
    }

Currently, this framework support three actions (update, query, delete).

For example (as in the demo1 project)

The result will of GET http://localhost:8888/limiterconfig?controller=DemoController&method=dynamicTest

{
  "applicationName": "demo1",
  "controllerName": "DemoController",
  "methodName": "dynamicTest",
  "baseExp": "#Headers['userid']",
  "path": "",
  "timeUnit": "MINUTES",
  "permits": 5,
  "deleted": false
}

If we want to update configuration, assign Content-Type as application/json, then excute PUT http://localhost:8888/limiterconfig, the request body as below:

{
  "applicationName": "demo1",
  "controllerName": "DemoController",
  "methodName": "dynamicTest",
  "baseExp": "#Headers['userid']",
  "path": "",
  "timeUnit": "MINUTES",
  "permits": 10,
  "deleted": false
}

If we want to delete a configuration, execute DELETE http://localhost:8888/limiterconfig?controller=DemoController&method=dynamicTest, the limiting configuration item for Controller DemoController and method dynamicTest will be deleted.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].