redislimiter-spring-boot
Отличная платформа для ограничения API для приложений Spring boot/cloud, особенно для микросервисных проектов.
git clone https://github.com/tangaiyun/redislimiter-spring-boot.git
cd redislimiter-spring-boot-starter
mvn clean install
Затем создайте проект Spring boot API, обратитесь к демонстрационному проекту «demo1», и вам нужно добавить зависимость в pom.xml.
<dependency>
<groupId>com.tay</groupId>
<artifactId>redislimiter-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
Для resources/application.yml
необходимо добавить следующие строки.
server:
port: 8888 #порт
spring:
application:
name: demo1 #имя приложения должно быть установлено, иначе приложение не запустится
redis-limiter: #Конфигурация ограничителя
redis-host: 127.0.0.1 #IP сервера Redis
check-action-timeout: 100 #проверка действия будет выполнена асинхронно, это значение тайм-аута
enable-dynamical-conf: true #включить переключатель для поддержки динамического ограничения конфигурации
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")
//ограничение на основе идентификатора пользователя, и один уникальный пользователь может посетить дважды за одну минуту, идентификатор пользователя содержится в заголовке HTTP
//аннотация RateLimiter означает, что эту конфигурацию нельзя изменить во время выполнения
@RateLimiter(base = "#Headers['userid']", permits = 2, timeUnit = TimeUnit.MINUTES)
public String test() {
return "test!";
}
@GetMapping("/dynamictest")
//ограничение основано на IP пользователя, и один уникальный IP может посещать пять раз за одну минуту, поэтому 'X-Real-IP' является ключом заголовка для IP
//аннотация DynamicRateLimiter означает, что эта конфигурация может быть изменена динамически во время выполнения
@DynamicRateLimiter(base = "#Headers['X-Real-IP']", permits = 5, timeUnit = TimeUnit.MINUTES)
public String dynamicTest() {
return "dynamictest!";
}
}
Запустите сервер Redis на локальном компьютере или с помощью Docker.
sudo docker run -d -p 6379:6379 redis
Это так здорово!
Вы можете использовать инструмент HTTP-клиента, такой как Postman, restd или curl, и получить URL-адрес http://localhost:8888/demo/test
. Не забудьте добавить пару значений userid=tom
в заголовок вашего HTTP-запроса. Вы сможете найти пользователя с идентификатором пользователя «tom», который сможет посетить этот URL дважды успешно максимум за одну минуту.
С помощью Postman/restd посетите http://localhost:8888/demo/dynamictest
с парой значений X-Real-IP=127.0.0.1
в вашем заголовке HTTP-запроса, вы сможете обнаружить, что только пять запросов с заголовком X-Real-IP=127.0.0.1
будут успешными за одну минуту.
spring:
redis-limiter:
redis-host: 127.0.0.1 # IP сервера Redis по умолчанию: 127.0.0.1
redis-port: 6379 # порт службы Redis по умолчанию: 6379
redis-password: test # пароль Redis по умолчанию: null
redis-connection-timeout: 2000 # тайм-аут подключения Redis по умолчанию: 2000
redis-pool-max-idle: 50 # максимальное количество простаивающих соединений Redis в пуле по умолчанию: 50
redis-pool-min-idle: ### Redis pool
| Параметр | Значение по умолчанию |
|:---|:---|
| redis-pool-max-idle | 10 |
| redis-pool-max-wait-millis | -1 |
| redis-pool-max-total | 200 |
### Описание
*redis-pool-max-idle* — максимальное количество незанятых соединений в пуле.
*redis-pool-max-wait-millis* — максимальное время ожидания соединения. По умолчанию установлено значение -1, что означает отсутствие ограничения на время ожидания.
*redis-pool-max-total* — максимальное общее количество соединений в пуле.
### Пример конфигурации
redis-key-prefix: #RL # префикс ключа для отслеживания посещений, по умолчанию: #RL check-action-timeout: 100 # время ожидания выполнения действия проверки, по умолчанию: 100 enable-dynamical-conf: true # переключатель включения динамической конфигурации, по умолчанию: false channel: #RLConfigChannel # канал публикации/подписки на события изменения конфигурации, по умолчанию: #RLConfigChannel
### Аннотации
@RateLimiter и @DynamicRateLimiter — эти две аннотации имеют одинаковые четыре атрибута (base, path, timeUnit, permits).
```java
@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, который определяет, на основе чего происходит ограничение (например, идентификатор пользователя, удалённый IP-адрес и т. д.). Если вы не назначите атрибут base, все запросы будут накапливаться как единое целое. «База» должна быть выражением Spel.
@RateLimiter(base = "#Headers['userid']", permits = 2, timeUnit = TimeUnit.MINUTES)
@DynamicRateLimiter(base = "#Headers['X-Real-IP']", permits = 5, timeUnit = TimeUnit.MINUTES)
В настоящее время выражение base поддерживает только получение значения из HTTP-заголовка и cookie. В контексте оценки выражения Spel они называются Headers и Cookies отдельно, поэтому два выражения действительны следующим образом:
"#Headers['X-Real-IP']"
"#Cookies['userid']"
Значение пути по умолчанию равно "", если вы его не установили. Когда путь имеет значение "", значение пути будет установлено как request.getRequestURI(). В общем случае это нормально. Но в одном особом случае вам следует явно установить путь.
Например:
@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;
}
GetMapping имеет PathVariable-{userid}. В этом случае мы не будем считать посещения на основе /user/001. Если мы установим значение пути равным /user, то все запросы, подобные /user/xxx, будут суммироваться на основе /user.
Допустимы четыре TimeUnits:
Количество посещений, разрешённых за единицу времени.
Аннотация @DynamicRateLimiter позволяет изменять конфигурацию динамически, мы можем изменить конфигурацию с помощью внутреннего RESTful API. Контроллер (@RequestParam("method")String method) { LimiterConfig limiterConfig = new LimiterConfig(); limiterConfig.setApplicationName(applicationName); limiterConfig.setControllerName(controller); limiterConfig.setMethodName(method); limiterConfig.setDeleted(true); publish(limiterConfig); }
В настоящее время этот фреймворк поддерживает три действия (обновление, запрос, удаление).
Например (как в проекте demo1):
Результатом 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
}
Если мы хотим обновить конфигурацию, назначьте Content-Type как application/json, затем выполните PUT-запрос к http://localhost:8888/limiterconfig
, тело запроса будет следующим:
{
"applicationName": "demo1",
"controllerName": "DemoController",
"methodName": "dynamicTest",
"baseExp": "#Headers['userid']",
"path": "",
"timeUnit": "MINUTES",
"permits": 10,
"deleted": false
}
Если мы хотим удалить конфигурацию, выполните DELETE-запрос к http://localhost:8888/limiterconfig?controller=DemoController&method=dynamicTest
, элемент конфигурации ограничения для контроллера DemoController
и метода dynamicTest
будет удалён.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )