Spring?Boot?實(shí)現(xiàn)?IP?限流的原理、實(shí)踐與利弊解析
一、引言
在當(dāng)今互聯(lián)網(wǎng)應(yīng)用的高并發(fā)場(chǎng)景下,為了保障系統(tǒng)的穩(wěn)定性和可用性,對(duì)請(qǐng)求進(jìn)行限流是一項(xiàng)至關(guān)重要的技術(shù)手段。其中,IP 限流是一種常見且有效的限流策略,它可以根據(jù)客戶端的 IP 地址對(duì)請(qǐng)求進(jìn)行限制,防止惡意攻擊或單個(gè) IP 的過(guò)度請(qǐng)求耗盡系統(tǒng)資源。本文將深入探討在 Spring Boot 中如何實(shí)現(xiàn) IP 限流,包括其原理、使用場(chǎng)景、優(yōu)缺點(diǎn),并給出完整的代碼案例。
二、IP 限流原理
2.1 令牌桶算法
令牌桶算法是一種常用的限流算法,其核心思想是系統(tǒng)以固定的速率向一個(gè)令牌桶中添加令牌,每個(gè)請(qǐng)求需要從令牌桶中獲取一個(gè)或多個(gè)令牌才能被處理。如果令牌桶中沒有足夠的令牌,請(qǐng)求將被拒絕或等待。對(duì)于 IP 限流,每個(gè) IP 地址都有一個(gè)獨(dú)立的令牌桶,系統(tǒng)會(huì)根據(jù)該 IP 的請(qǐng)求情況動(dòng)態(tài)分配和消耗令牌。
2.2 漏桶算法
漏桶算法的原理類似于一個(gè)底部有漏洞的水桶,無(wú)論請(qǐng)求的速率如何,漏桶都會(huì)以固定的速率處理請(qǐng)求。當(dāng)請(qǐng)求的速率超過(guò)漏桶的處理能力時(shí),多余的請(qǐng)求會(huì)在桶中堆積,直到桶滿,此時(shí)新的請(qǐng)求將被拒絕。在 IP 限流中,每個(gè) IP 地址對(duì)應(yīng)一個(gè)漏桶,系統(tǒng)會(huì)按照固定的速率處理該 IP 的請(qǐng)求。
三、使用場(chǎng)景
3.1 防止惡意攻擊
惡意攻擊者可能會(huì)使用單個(gè) IP 地址發(fā)起大量的請(qǐng)求,試圖耗盡系統(tǒng)資源或獲取敏感信息。通過(guò) IP 限流,可以限制單個(gè) IP 的請(qǐng)求頻率,有效抵御此類攻擊。
3.2 控制資源使用
在共享資源的系統(tǒng)中,某些用戶可能會(huì)過(guò)度使用資源,影響其他用戶的正常使用。通過(guò) IP 限流,可以確保每個(gè) IP 地址的資源使用在合理范圍內(nèi),提高系統(tǒng)的整體性能。
3.3 遵守服務(wù)協(xié)議
有些服務(wù)提供商可能會(huì)對(duì)每個(gè) IP 地址的請(qǐng)求頻率進(jìn)行限制,以遵守相關(guān)的服務(wù)協(xié)議。通過(guò)在應(yīng)用層實(shí)現(xiàn) IP 限流,可以確保系統(tǒng)的請(qǐng)求行為符合規(guī)定。
四、優(yōu)缺點(diǎn)分析
4.1 優(yōu)點(diǎn)
精準(zhǔn)控制:可以針對(duì)每個(gè) IP 地址進(jìn)行精確的請(qǐng)求限制,有效防止單個(gè) IP 的過(guò)度請(qǐng)求。
實(shí)現(xiàn)簡(jiǎn)單:相比于其他復(fù)雜的限流策略,IP 限流的實(shí)現(xiàn)相對(duì)簡(jiǎn)單,不需要復(fù)雜的算法和配置。
易于維護(hù):由于每個(gè) IP 的限流規(guī)則相對(duì)獨(dú)立,維護(hù)和管理起來(lái)比較方便。
4.2 缺點(diǎn)
IP 偽裝繞過(guò):惡意攻擊者可以通過(guò) IP 代理或 VPN 等方式偽裝自己的 IP 地址,繞過(guò) IP 限流的限制。
影響正常用戶:在某些情況下,正常用戶可能會(huì)因?yàn)榫W(wǎng)絡(luò)環(huán)境等原因被錯(cuò)誤地限流,影響用戶體驗(yàn)。
不能應(yīng)對(duì)分布式攻擊:對(duì)于分布式拒絕服務(wù)(DDoS)攻擊,IP 限流只能對(duì)單個(gè) IP 進(jìn)行限制,無(wú)法有效應(yīng)對(duì)大量不同 IP 地址的攻擊。
五、完整代碼案例
5.1 項(xiàng)目搭建
首先,創(chuàng)建一個(gè) Spring Boot 項(xiàng)目,并添加以下依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 用于實(shí)現(xiàn)令牌桶算法 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>5.2 實(shí)現(xiàn) IP 限流過(guò)濾器
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Component
public class IpRateLimitFilter extends OncePerRequestFilter {
private static final int MAX_REQUESTS_PER_SECOND = 10; // 每個(gè) IP 每秒最大請(qǐng)求數(shù)
private final Map<String, RateLimiter> rateLimiters = new HashMap<>();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String clientIp = getClientIp(request);
RateLimiter rateLimiter = rateLimiters.computeIfAbsent(clientIp, k -> RateLimiter.create(MAX_REQUESTS_PER_SECOND));
if (!rateLimiter.tryAcquire()) {
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
response.getWriter().write("Too many requests from this IP.");
return;
}
filterChain.doFilter(request, response);
}
private String getClientIp(HttpServletRequest request) {
String xffHeader = request.getHeader("X-Forwarded-For");
if (xffHeader == null) {
return request.getRemoteAddr();
}
return xffHeader.split(",")[0];
}
}5.3 配置過(guò)濾器
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<IpRateLimitFilter> ipRateLimitFilterRegistration() {
FilterRegistrationBean<IpRateLimitFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new IpRateLimitFilter());
registration.addUrlPatterns("/*"); // 對(duì)所有請(qǐng)求進(jìn)行限流
registration.setOrder(1);
return registration;
}
}5.4 創(chuàng)建測(cè)試控制器
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "Hello, this is a test API.";
}
}5.5 測(cè)試
啟動(dòng) Spring Boot 項(xiàng)目,使用工具(如 Postman)模擬不同 IP 地址的請(qǐng)求。當(dāng)某個(gè) IP 的請(qǐng)求頻率超過(guò)每秒 10 次時(shí),會(huì)收到 Too many requests from this IP. 的響應(yīng)。
六、總結(jié)
在 Spring Boot 中實(shí)現(xiàn) IP 限流是一種簡(jiǎn)單而有效的方式來(lái)保障系統(tǒng)的穩(wěn)定性和可用性。通過(guò)令牌桶算法或漏桶算法,可以對(duì)每個(gè) IP 地址的請(qǐng)求頻率進(jìn)行精確控制。雖然 IP 限流存在一些缺點(diǎn),但在大多數(shù)場(chǎng)景下,它仍然是一種不可或缺的限流策略。通過(guò)本文的代碼案例,你可以快速在自己的 Spring Boot 項(xiàng)目中實(shí)現(xiàn) IP 限流功能。
到此這篇關(guān)于Spring Boot 實(shí)現(xiàn) IP 限流的原理、實(shí)踐與利弊解析的文章就介紹到這了,更多相關(guān)Spring Boot IP 限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring?Boot?實(shí)現(xiàn)?IP?限流(保障系統(tǒng)穩(wěn)定性的關(guān)鍵技術(shù))
- SpringBoot使用Redis對(duì)用戶IP進(jìn)行接口限流的項(xiàng)目實(shí)踐
- SpringBoot使用Redis對(duì)用戶IP進(jìn)行接口限流的示例詳解
- SpringBoot高并發(fā)下控制限流的幾種實(shí)現(xiàn)方法
- Spring Boot集成Resilience4J實(shí)現(xiàn)限流/重試/隔離
- Spring Boot使用Redisson實(shí)現(xiàn)滑動(dòng)窗口限流的項(xiàng)目實(shí)踐
- Spring Boot高可用限流三種實(shí)現(xiàn)解決方案
相關(guān)文章
SpringBoot集成AOP實(shí)現(xiàn)日志記錄與接口權(quán)限校驗(yàn)
本文主要介紹了SpringBoot集成AOP實(shí)現(xiàn)日志記錄與接口權(quán)限校驗(yàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-02-02
JAVA后臺(tái)轉(zhuǎn)換成樹結(jié)構(gòu)數(shù)據(jù)返回給前端的實(shí)現(xiàn)方法
這篇文章主要介紹了JAVA后臺(tái)轉(zhuǎn)換成樹結(jié)構(gòu)數(shù)據(jù)返回給前端的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
SpringBoot+EasyPOI實(shí)現(xiàn)百萬(wàn)級(jí)數(shù)據(jù)導(dǎo)出Excel實(shí)戰(zhàn)指南
這篇文章主要為大家詳細(xì)介紹了一款基于 EasyPOI 和 Apache POI SXSSF 的批量Excel導(dǎo)出工具類 BatchExcelExporter,支持大數(shù)據(jù)量分頁(yè)處理,下面小編就來(lái)和大家詳細(xì)介紹一下吧2025-09-09
Java實(shí)現(xiàn)的DES加密解密工具類實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)的DES加密解密工具類,結(jié)合具體實(shí)例形式分析了Java實(shí)現(xiàn)的DES加密解密工具類定義與使用方法,需要的朋友可以參考下2017-09-09
fasterxml jackson反序列化時(shí)對(duì)于非靜態(tài)內(nèi)部類報(bào)錯(cuò)問題及解決
這篇文章主要介紹了fasterxml jackson反序列化時(shí)對(duì)于非靜態(tài)內(nèi)部類報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Java中JSON字符串與java對(duì)象的互換實(shí)例詳解
這篇文章主要介紹了在java中,JSON字符串與java對(duì)象的相互轉(zhuǎn)換實(shí)例詳解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
Spring JPA學(xué)習(xí)之delete方法示例詳解
這篇文章主要為大家介紹了Spring JPA學(xué)習(xí)delete方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
一次 Java 服務(wù)性能優(yōu)化實(shí)例詳解
這篇文章主要介紹了一次 Java 服務(wù)性能優(yōu)化實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07

