SpringBoot接口訪問頻率限制的實現(xiàn)方式
概述
接口訪問頻率限制是通過在一定時間內(nèi)限制用戶對接口的訪問次數(shù)來實現(xiàn)的。常見的限流算法包括令牌桶算法(Token Bucket)、漏桶算法(Leaky Bucket)、固定窗口計數(shù)器(Fixed Window Counter)和滑動窗口計數(shù)器(Sliding Window Counter)等。在Spring Boot中,我們可以通過多種方式來實現(xiàn)接口的限流,如使用過濾器、攔截器或者借助第三方庫。
為什么需要接口訪問頻率限制
- 防止惡意攻擊:通過限制接口的訪問頻率,可以有效防止惡意用戶或機器人頻繁訪問接口,導致系統(tǒng)資源耗盡。
- 提升系統(tǒng)穩(wěn)定性:在高并發(fā)場景下,限流可以有效保護后端服務,避免因流量過大而導致系統(tǒng)崩潰。
- 提升用戶體驗:合理的限流可以保障所有用戶都能獲得較好的服務質(zhì)量,避免個別用戶過度使用資源。
常見的實現(xiàn)方式
基于過濾器的實現(xiàn)
過濾器是Java Web應用中常用的一種組件,它可以在請求到達Servlet之前對請求進行預處理。通過在過濾器中實現(xiàn)限流邏輯,可以對所有的HTTP請求進行統(tǒng)一的限流控制。
基于攔截器的實現(xiàn)
攔截器是Spring框架提供的一種處理器,可以在請求處理之前和之后進行相關操作。相比于過濾器,攔截器可以更加細粒度地控制請求,適用于需要針對某些特定接口進行限流的場景。
基于第三方庫Bucket4j的實現(xiàn)
Bucket4j是一個Java實現(xiàn)的高性能限流庫,它支持多種限流算法,如令牌桶算法。通過使用Bucket4j,可以輕松地在Spring Boot應用中實現(xiàn)復雜的限流邏輯,并且它還提供了豐富的配置選項和統(tǒng)計功能。
實際代碼示例
基于過濾器實現(xiàn)Rate Limiting
首先,我們需要創(chuàng)建一個自定義的過濾器類,并在其中實現(xiàn)限流邏輯。以下是一個示例代碼:
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
public class RateLimitingFilter implements Filter {
private final ConcurrentMap<String, Long> requestCounts = new ConcurrentHashMap<>();
private static final long ALLOWED_REQUESTS_PER_MINUTE = 60;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化過濾器
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String clientIp = httpRequest.getRemoteAddr();
long currentTimeMillis = System.currentTimeMillis();
requestCounts.putIfAbsent(clientIp, currentTimeMillis);
long lastRequestTime = requestCounts.get(clientIp);
if (TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - lastRequestTime) < 1) {
long requestCount = requestCounts.values().stream().filter(time -> TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - time) < 1).count();
if (requestCount > ALLOWED_REQUESTS_PER_MINUTE) {
httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
httpResponse.getWriter().write("Too many requests");
return;
}
}
requestCounts.put(clientIp, currentTimeMillis);
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 銷毀過濾器
}
}
然后,在Spring Boot應用的配置類中注冊這個過濾器:
import 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("/api/*");
return registrationBean;
}
}
基于攔截器實現(xiàn)Rate Limiting
首先,我們需要創(chuàng)建一個自定義的攔截器類,并在其中實現(xiàn)限流邏輯。以下是一個示例代碼:
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
public class RateLimitingInterceptor implements HandlerInterceptor {
private final ConcurrentMap<String, Long> requestCounts = new ConcurrentHashMap<>();
private static final long ALLOWED_REQUESTS_PER_MINUTE = 60;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String clientIp = request.getRemoteAddr();
long currentTimeMillis = System.currentTimeMillis();
requestCounts.putIfAbsent(clientIp, currentTimeMillis);
long lastRequestTime = requestCounts.get(clientIp);
if (TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - lastRequestTime) < 1) {
long requestCount = requestCounts.values().stream().filter(time -> TimeUnit.MILLISECONDS.toMinutes(currentTimeMillis - time) < 1).count();
if (requestCount > ALLOWED_REQUESTS_PER_MINUTE) {
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
response.getWriter().write("Too many requests");
return false;
}
}
requestCounts.put(clientIp, currentTimeMillis);
return true;
}
}
然后,在Spring Boot應用的配置類中注冊這個攔截器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private RateLimitingInterceptor rateLimitingInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(rateLimitingInterceptor).addPathPatterns("/api/**");
}
}
使用Bucket4j實現(xiàn)Rate Limiting
首先,在項目中引入Bucket4j依賴:
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>7.0.0</version>
</dependency>
然后,創(chuàng)建一個自定義的過濾器類,并在其中實現(xiàn)限流邏輯:
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class Bucket4jRateLimitingFilter implements Filter {
private final ConcurrentMap<String, Bucket> buckets = new ConcurrentHashMap<>();
@
Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化過濾器
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String clientIp = httpRequest.getRemoteAddr();
Bucket bucket = buckets.computeIfAbsent(clientIp, this::newBucket);
if (bucket.tryConsume(1)) {
chain.doFilter(request, response);
} else {
httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
httpResponse.getWriter().write("Too many requests");
}
}
private Bucket newBucket(String clientIp) {
return Bucket4j.builder()
.addLimit(Bandwidth.classic(60, Refill.greedy(60, Duration.ofMinutes(1))))
.build();
}
@Override
public void destroy() {
// 銷毀過濾器
}
}
然后,在Spring Boot應用的配置類中注冊這個過濾器:
import 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("/api/*");
return registrationBean;
}
}
最佳實踐
選擇合適的限流算法
- 令牌桶算法:適用于需要平滑突發(fā)流量的場景。
- 漏桶算法:適用于需要嚴格控制流量的場景。
- 固定窗口計數(shù)器:適用于對簡單限流要求的場景。
- 滑動窗口計數(shù)器:適用于需要精確控制限流的場景。
優(yōu)化性能
- 減少鎖競爭:在高并發(fā)環(huán)境下,盡量減少鎖的使用,可以采用無鎖數(shù)據(jù)結構或者線程安全的數(shù)據(jù)結構。
- 緩存結果:對于頻繁訪問的數(shù)據(jù),可以考慮進行緩存,減少數(shù)據(jù)庫查詢的次數(shù)。
- 異步處理:對于耗時的操作,可以考慮采用異步處理,提高系統(tǒng)的響應速度。
記錄日志和監(jiān)控
- 記錄訪問日志:記錄每次接口訪問的詳細信息,包括請求時間、IP地址、請求路徑等。
- 監(jiān)控限流情況:對限流情況進行監(jiān)控,及時發(fā)現(xiàn)和處理異常流量。
- 報警機制:設置限流報警機制,當流量超過預設閾值時,及時報警。
總結
本文詳細介紹了在Spring Boot中實現(xiàn)接口訪問頻率限制的幾種方法,包括基于過濾器、攔截器和第三方庫Bucket4j的實現(xiàn)。通過合理的限流策略,可以有效防止惡意攻擊,提升系統(tǒng)的穩(wěn)定性和用戶體驗。在實際應用中,選擇合適的限流算法和實現(xiàn)方式,并結合業(yè)務需求進行優(yōu)化,是確保系統(tǒng)高效運行的關鍵。
以上就是SpringBoot接口訪問頻率限制的實現(xiàn)方式的詳細內(nèi)容,更多關于SpringBoot接口訪問頻率限制的資料請關注腳本之家其它相關文章!
相關文章
Spring框架基于AOP實現(xiàn)簡單日志管理步驟解析
這篇文章主要介紹了Spring框架基于AOP實現(xiàn)簡單日志管理步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-06-06
LoggingEventAsyncDisruptorAppender類執(zhí)行流程源碼解讀
這篇文章主要介紹了LoggingEventAsyncDisruptorAppender類執(zhí)行流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12
java實現(xiàn)給圖片加鋪滿的網(wǎng)格式文字水印
這篇文章主要給大家介紹了關于java實現(xiàn)給圖片加鋪滿的網(wǎng)格式文字水印的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01
引入QQ郵箱發(fā)送驗證碼進行安全校驗功能實現(xiàn)
最近遇到這樣的需求用戶輸入自己的郵箱,點擊獲取驗證碼,后臺會發(fā)送一封郵件到對應郵箱中,怎么實現(xiàn)呢?下面小編給大家?guī)砹艘隥Q郵箱發(fā)送驗證碼進行安全校驗功能,需要的朋友可以參考下2023-02-02

