В микросервисах и системах с высоким уровнем параллелизма ограничение скорости является очень важным техническим средством защиты системы от перегрузки и обеспечения стабильности сервиса. Ограничение тока может контролировать скорость запросов и не позволять одному клиенту или злоумышленнику потреблять слишком много ресурсов и тем самым влиять на других пользователей.
Общие алгоритмы ограничения тока включают в себя:
Используя Spring Boot для реализации ограничения тока, вы можете использовать следующие методы:
Ниже мы представляем реализацию этих методов соответственно.
Сначала мы создаем фильтр, ограничивающий поток, с помощью AtomicInteger
или Semaphore
контролировать частоту запросов.
javaкопировать импорт org.springframework.stereotype.Component;
импортировать javax.servlet.Filter;
импортировать javax.servlet.FilterChain;
импортировать javax.servlet.FilterConfig;
импортировать javax.servlet.ServletException;
импортировать javax.servlet.ServletRequest;
импортировать javax.servlet.ServletResponse;
импортировать javax.servlet.http.HttpServletResponse;
импортировать java.io.IOException;
импортировать java.util.concurrent.Semaphore;
@Компонент
публичный класс RateLimitingFilter реализует фильтр {
частный статический финал int MAX_REQUESTS_PER_SECOND = 10;
частный семафор семафор = новый семафор (MAX_REQUESTS_PER_SECOND);
@Override
public void init(FilterConfig filterConfig) выдает ServletException {
}
@Override
public void doFilter (запрос ServletRequest, ответ ServletResponse, цепочка FilterChain)
выдает IOException, ServletException {
если (семафор.tryAcquire()) {
пытаться {
Chain.doFilter(запрос, ответ);
} окончательно {
семафор.выпуск();
}
} еще {
((HttpServletResponse) ответ).setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
}
}
@Override
общественный недействительный уничтожить () {
}
}
существовать Spring Boot В приложении фильтр прописывается автоматически, нужно только добавить @Component
Просто аннотируйте. Однако вы также можете настроить его вручную:
javaкопировать импорт кода org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<RateLimitingFilter> loggingFilter() {
FilterRegistrationBean<RateLimitingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new RateLimitingFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
существовать pom.xml
Добавить Bucket4j полагаться:
xmlкопироватькод<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>6.2.0</version>
</dependency>
javaкопировать импорт кода com.github.bucket4j.Bandwidth;
import com.github.bucket4j.Bucket;
import com.github.bucket4j.Refill;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
@Component
public class Bucket4jRateLimitingFilter implements Filter {
private static final int CAPACITY = 10;
private static final int REFILL_TOKENS = 10;
private static final Duration REFILL_DURATION = Duration.ofSeconds(1);
private final Bucket bucket;
public Bucket4jRateLimitingFilter() {
Bandwidth limit = Bandwidth.classic(CAPACITY, Refill.greedy(REFILL_TOKENS, REFILL_DURATION));
this.bucket = Bucket.builder().addLimit(limit).build();
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (bucket.tryConsume(1)) {
chain.doFilter(request, response);
} else {
((HttpServletResponse) response).setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
}
}
@Override
public void destroy() {
}
}
Аналогично первому методу, просто настройте фильтр:
javaкопировать импорт кода org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<Bucket4jRateLimitingFilter> loggingFilter() {
FilterRegistrationBean<Bucket4jRateLimitingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new Bucket4jRateLimitingFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
существовать pom.xml
Добавить Redis и Redisson полагаться:
xmlкопироватькод<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.15.6</version>
</dependency>
существовать application.properties
Средняя конфигурация Redis:
propertiesкопироватькодspring.redis.host=localhost
spring.redis.port=6379
javaкопировать импорт кода org.redisson.api.RRateLimiter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class RedisRateLimitingFilter implements Filter {
@Autowired
private RedissonClient redissonClient;
private RRateLimiter rateLimiter;
@Bean
public RRateLimiter rateLimiter() {
RRateLimiter rateLimiter = redissonClient.getRateLimiter("rateLimiter");
rateLimiter.trySetRate(RRateType.OVERALL, 10, 1, RateIntervalUnit.SECONDS);
return rateLimiter;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.rateLimiter = rateLimiter();
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (rateLimiter.tryAcquire(1)) {
chain.doFilter(request, response);
} else {
((HttpServletResponse) response).setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
}
}
@Override
public void destroy() {
}
}
Как и прежде, настройте фильтр:
javaкопировать импорт кода org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<RedisRateLimitingFilter> loggingFilter() {
FilterRegistrationBean<RedisRateLimitingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new RedisRateLimitingFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
существоватьв этом руководстве,Мы представили трисуществовать Spring Boot Методы реализации ограничения тока в:
Каждый метод имеет свои преимущества и недостатки и применимые сценарии.,Вы можете выбрать подходящее решение, исходя из ваших конкретных потребностей. Надеюсь, эта статья поможет вам реализовать функцию Реализация ограничений тока в проекте.,Обеспечить стабильность и надежность системы.