欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實(shí)現(xiàn)IP限流的示例代碼

 更新時間:2025年06月18日 10:07:32   作者:微特爾普拉斯  
在高并發(fā)的互聯(lián)網(wǎng)應(yīng)用中,系統(tǒng)穩(wěn)定性面臨嚴(yán)峻挑戰(zhàn),爬蟲、以及不合理的接口調(diào)用都可能導(dǎo)致系統(tǒng)資源耗盡,影響正常用戶體驗(yàn),為了保障系統(tǒng)的穩(wěn)定性和可用性,本文將深入探討如何在 Spring Boot 中實(shí)現(xiàn) IP 限流,需要的朋友可以參考下

一、引言

在高并發(fā)的互聯(lián)網(wǎng)應(yīng)用中,系統(tǒng)穩(wěn)定性面臨嚴(yán)峻挑戰(zhàn)。惡意攻擊、爬蟲、以及不合理的接口調(diào)用都可能導(dǎo)致系統(tǒng)資源耗盡,影響正常用戶體驗(yàn)。為了保障系統(tǒng)的穩(wěn)定性和可用性,對請求進(jìn)行限流是至關(guān)重要的技術(shù)手段。本文將深入探討如何在 Spring Boot 中實(shí)現(xiàn) IP 限流,包括其原理、使用場景、優(yōu)缺點(diǎn)、多種實(shí)現(xiàn)方式,并給出完整的代碼案例,助您構(gòu)建更加健壯的應(yīng)用。

二、IP 限流原理:深入解析

IP 限流,顧名思義,就是根據(jù)客戶端的 IP 地址對請求進(jìn)行頻率限制。其核心在于控制每個 IP 地址在單位時間內(nèi)允許訪問的次數(shù),從而避免單個 IP 大量占用資源,保證系統(tǒng)整體的公平性。以下介紹兩種常用的限流算法:

2.1 令牌桶算法 (Token Bucket)

工作機(jī)制:

  • 系統(tǒng)以恒定速率 ( r ) 向令牌桶中放入令牌。
  • 每個請求需要從令牌桶中獲取一個令牌才能被處理。
  • 如果令牌桶為空,則請求被拒絕或等待。
  • 令牌桶具有最大容量 ( b ),當(dāng)令牌數(shù)量達(dá)到上限時,新添加的令牌會被丟棄。

優(yōu)點(diǎn):

  • 平滑突發(fā)流量: 允許短時間內(nèi)突發(fā)大量請求,因?yàn)榱钆仆爸锌赡芊e累了足夠的令牌。
  • 容錯性高: 即使短時間內(nèi)沒有請求,令牌也會持續(xù)積累,允許后續(xù)的請求 burst。
  • 動態(tài)適應(yīng): 更適合處理動態(tài)變化的請求,可以在一定程度上應(yīng)對流量高峰。

2.2 漏桶算法 (Leaky Bucket)

工作機(jī)制:

  • 請求被放入漏桶中,漏桶以恒定速率 ( r ) 處理請求。
  • 當(dāng)請求的速率超過漏桶的處理能力時,多余的請求會在桶中堆積。
  • 如果桶滿,則新的請求會被丟棄。

優(yōu)點(diǎn):

  • 嚴(yán)格控制速率: 能嚴(yán)格控制輸出速率,保證請求以固定速度被處理。
  • 平滑輸出: 可以將突發(fā)流量轉(zhuǎn)化為平滑的輸出流量。

缺點(diǎn):

  • 難以應(yīng)對突發(fā)流量: 即使系統(tǒng)資源充足,也無法快速處理突發(fā)請求,容易導(dǎo)致請求被拒絕。

2.3 令牌桶與漏桶算法對比

特性令牌桶算法漏桶算法
流量控制允許突發(fā)流量,平均速率限制嚴(yán)格控制速率,平滑輸出
適用場景需要容忍一定突發(fā)流量的場景,如 API 限流對速率有嚴(yán)格要求的場景,如消息隊列削峰填谷
實(shí)現(xiàn)復(fù)雜度相對簡單相對簡單
動態(tài)調(diào)整容易實(shí)現(xiàn)動態(tài)調(diào)整令牌生成速率和桶容量調(diào)整輸出速率和桶容量相對困難

三、IP 限流的使用場景:應(yīng)用廣泛

IP 限流作為一種基礎(chǔ)且有效的限流手段,在各種場景中都有廣泛的應(yīng)用:

3.1 API 網(wǎng)關(guān)限流

在 API 網(wǎng)關(guān)層實(shí)現(xiàn) IP 限流,可以統(tǒng)一管理和控制所有 API 的請求頻率,是微服務(wù)架構(gòu)中保護(hù)后端服務(wù)的關(guān)鍵措施。

3.2 Web 應(yīng)用安全防護(hù)

對登錄、注冊、找回密碼等敏感接口進(jìn)行 IP 限流,防止暴力 破解和惡意注冊,增強(qiáng)應(yīng)用的安全性。

3.3 微服務(wù)架構(gòu)

在微服務(wù)架構(gòu)中,對每個微服務(wù)的接口進(jìn)行 IP 限流,保障服務(wù)的穩(wěn)定性和可用性,防止服務(wù)雪崩。

3.4 防止惡意爬蟲

限制爬蟲程序的訪問頻率,防止爬蟲過度抓取數(shù)據(jù),影響正常用戶體驗(yàn)。

3.5 控制資源使用

在共享資源的系統(tǒng)中,限制單個 IP 地址的資源使用,確保每個用戶都能公平地使用資源。

四、IP 限流的優(yōu)缺點(diǎn)分析:理性看待

4.1 優(yōu)點(diǎn)

  • 精準(zhǔn)控制: 可以針對每個 IP 地址進(jìn)行精確的請求限制,有效防止單個 IP 的過度請求。
  • 實(shí)現(xiàn)簡單: 相比于其他復(fù)雜的限流策略,IP 限流的實(shí)現(xiàn)相對簡單,不需要復(fù)雜的算法和配置。
  • 易于維護(hù): 由于每個 IP 的限流規(guī)則相對獨(dú)立,維護(hù)和管理起來比較方便。

4.2 缺點(diǎn)

  • IP 偽裝繞過: 惡意攻擊者可以通過 IP 代理或 VPN 等方式偽裝自己的 IP 地址,繞過 IP 限流的限制。
  • 影響正常用戶: 在某些情況下,正常用戶可能會因?yàn)榫W(wǎng)絡(luò)環(huán)境等原因被錯誤地限流,影響用戶體驗(yàn)。
  • IP 地址池問題: 如果多個用戶共享同一個公網(wǎng) IP 地址,可能會導(dǎo)致正常用戶的請求被錯誤地限流。
  • 無法區(qū)分用戶: IP 限流只能根據(jù) IP 地址進(jìn)行限制,無法區(qū)分不同的用戶,可能導(dǎo)致惡意用戶利用合法用戶的 IP 地址發(fā)起攻擊。
  • 不能應(yīng)對分布式攻擊: 對于分布式拒絕服務(wù)(DDoS)攻擊,IP 限流只能對單個 IP 進(jìn)行限制,無法有效應(yīng)對大量不同 IP 地址的攻擊。
  • 維護(hù)成本: 如果需要對大量 IP 地址進(jìn)行限流,維護(hù)成本可能會比較高,需要考慮使用更高效的存儲方案,例如 Redis 或數(shù)據(jù)庫。

五、Spring Boot 實(shí)現(xiàn) IP 限流:代碼案例

以下提供兩種基于 Spring Boot 的 IP 限流實(shí)現(xiàn)方式:

5.1 基于 Guava RateLimiter 的 IP 限流過濾器(推薦)

這種方式使用 Guava 的 RateLimiter 實(shí)現(xiàn)令牌桶算法,簡單高效,易于配置。

1. 項目搭建:

創(chuàng)建一個 Spring Boot 項目,并添加以下依賴:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>31.1-jre</version>
    </dependency>
</dependencies>

2. 創(chuàng)建 RateLimiterService:

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
import java.util.concurrent.TimeUnit;
 
@Service
public class RateLimiterService {
 
    private static final Logger logger = LoggerFactory.getLogger(RateLimiterService.class);
 
    @Value("${rate.limit.permitsPerSecond:10}") // 默認(rèn)值 10
    private double permitsPerSecond;
 
    // 使用 LoadingCache 緩存每個 IP 的 RateLimiter
    private final LoadingCache<String, RateLimiter> rateLimiterCache = CacheBuilder.newBuilder()
            .expireAfterWrite(1, TimeUnit.MINUTES) // 緩存 1 分鐘
            .build(new CacheLoader<String, RateLimiter>() {
                @Override
                public RateLimiter load(String ip) {
                    logger.info("Creating RateLimiter for IP: {}, rate: {}", ip, permitsPerSecond);
                    return RateLimiter.create(permitsPerSecond);
                }
            });
 
    /**
     * 嘗試獲取令牌
     * @param ip 客戶端 IP 地址
     * @return true: 允許訪問, false: 限流
     */
    public boolean tryAcquire(String ip) {
        RateLimiter rateLimiter = rateLimiterCache.getUnchecked(ip);
        return rateLimiter.tryAcquire();
    }
 
}

3. 創(chuàng)建 IP 限流過濾器:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
 
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
 
@Component
public class IpRateLimitFilter extends OncePerRequestFilter {
 
    private static final Logger logger = LoggerFactory.getLogger(IpRateLimitFilter.class);
 
    @Autowired
    private RateLimiterService rateLimiterService;
 
    @Value("${rate.limit.enabled:true}")
    private boolean rateLimitEnabled;
 
    @Value("${rate.limit.excludePatterns:}") // 排除的URL,用逗號分隔
    private String excludePatterns;
 
 
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
 
        if (!rateLimitEnabled) {
            filterChain.doFilter(request, response);
            return; // 如果禁用限流,直接放行
        }
 
        // 排除不需要限流的URL
        String requestURI = request.getRequestURI();
        if (excludePatterns != null && !excludePatterns.isEmpty()) {
             String[] patterns = excludePatterns.split(",");
             for (String pattern : patterns) {
                if (requestURI.startsWith(pattern.trim())) {
                    filterChain.doFilter(request, response);
                    return;
                 }
             }
        }
 
 
        String clientIp = getClientIp(request);
 
        if (rateLimiterService.tryAcquire(clientIp)) {
            filterChain.doFilter(request, response); // 允許訪問
        } else {
            logger.warn("Rate limit exceeded for IP: {}", clientIp);
            response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
            response.getWriter().write("Too many requests from this IP.");
        }
    }
 
    private String getClientIp(HttpServletRequest request) {
        String xffHeader = request.getHeader("X-Forwarded-For");
        if (xffHeader == null) {
            return request.getRemoteAddr();
        }
        return xffHeader.split(",")[0];
    }
}

4. 配置過濾器:

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(IpRateLimitFilter ipRateLimitFilter) {
        FilterRegistrationBean<IpRateLimitFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(ipRateLimitFilter);
        registration.addUrlPatterns("/*"); // 對所有請求進(jìn)行限流
        registration.setOrder(1);
        return registration;
    }
}

5. 創(chuàng)建測試控制器:

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.";
    }
}

6. application.properties 配置:

# 限流配置
rate.limit.enabled=true
rate.limit.permitsPerSecond=10
rate.limit.excludePatterns=/health,/metrics # 排除的URL

5.2 基于 ConcurrentHashMap 的 IP 限流

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
 
@Component
public class IPRequestRateLimiter implements HandlerInterceptor {
    private final int REQUEST_LIMIT = 10;  // 每秒最大請求數(shù)
    private final Map<String, AtomicInteger> requestCountsPerIP = new ConcurrentHashMap<>();
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ipAddress = request.getRemoteAddr();
 
        // 1. 初始化計數(shù)器
        requestCountsPerIP.computeIfAbsent(ipAddress, k -> new AtomicInteger(0));
 
        // 2. 檢查請求是否超限
        if (requestCountsPerIP.get(ipAddress).incrementAndGet() > REQUEST_LIMIT) {
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.getWriter().write("Too many requests from this IP. Please try again later.");
            return false; // 阻止請求
        }
        return true; // 允許請求
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String ipAddress = request.getRemoteAddr();
 
        // 3. 請求完成后,減少計數(shù)
        requestCountsPerIP.get(ipAddress).decrementAndGet();
    }
}

注意: 此方式只是一個簡易的實(shí)現(xiàn),存在時間窗口不精準(zhǔn)等問題,生產(chǎn)環(huán)境不建議使用.

5.3 測試

啟動 Spring Boot 項目,使用工具(如 Postman)模擬不同 IP 地址的請求。當(dāng)某個 IP 的請求頻率超過配置的限制時,會收到 Too many requests from this IP. 的響應(yīng)。

六、進(jìn)階特性:提升 IP 限流的可靠性

  • 動態(tài)調(diào)整限流規(guī)則: 可以根據(jù)系統(tǒng)負(fù)載情況動態(tài)調(diào)整 permitsPerSecond 的值,實(shí)現(xiàn)更靈活的限流策略。可以通過 Spring Cloud Config 等配置中心實(shí)現(xiàn)動態(tài)更新。
  • 黑名單和白名單: 支持黑名單和白名單 IP 地址,對特定的 IP 地址進(jìn)行特殊處理??梢允褂?Redis 等緩存存儲黑白名單,并定期更新。
  • 監(jiān)控和告警: 集成監(jiān)控系統(tǒng)(如 Prometheus、Grafana),實(shí)時監(jiān)控 IP 限流的效果,并設(shè)置告警規(guī)則,及時發(fā)現(xiàn)異常情況。
  • 分布式限流: 對于分布式系統(tǒng),需要使用分布式鎖或 Redis 等技術(shù)實(shí)現(xiàn)分布式限流,保證所有節(jié)點(diǎn)使用相同的限流規(guī)則。
  • 更精細(xì)化的限流維度: 可以結(jié)合用戶 ID、API 接口等維度進(jìn)行更精細(xì)化的限流,例如限制每個用戶每天可以訪問某個 API 接口的次數(shù)。

七、總結(jié)

在 Spring Boot 中實(shí)現(xiàn) IP 限流是一種簡單而有效的方式來保障系統(tǒng)的穩(wěn)定性和可用性。通過本文的詳細(xì)介紹和代碼案例,相信您已經(jīng)掌握了 IP 限流的基本原理和實(shí)現(xiàn)方式。在實(shí)際應(yīng)用中,請根據(jù)您的具體需求選擇合適的限流算法和實(shí)現(xiàn)方式,并結(jié)合其他安全措施,構(gòu)建更加健壯的系統(tǒng)。請記住,安全策略應(yīng)該是全面的,限流只是其中一部分。

以上就是SpringBoot實(shí)現(xiàn)IP限流的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot IP限流的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • ant使用指南詳細(xì)入門教程

    ant使用指南詳細(xì)入門教程

    這篇文章主要介紹了ant使用指南詳細(xì)入門教程,本文詳細(xì)的講解了安裝、驗(yàn)證安裝、使用方法、使用實(shí)例、ant命令等內(nèi)容,需要的朋友可以參考下
    2015-06-06
  • 詳解Java中使用泛型實(shí)現(xiàn)快速排序算法的方法

    詳解Java中使用泛型實(shí)現(xiàn)快速排序算法的方法

    這篇文章主要介紹了Java中使用泛型實(shí)現(xiàn)快速排序算法的方法,快速排序的平均時間復(fù)雜度為(n\log n),文中的方法立足于基礎(chǔ)而并沒有考慮優(yōu)化處理,需要的朋友可以參考下
    2016-05-05
  • java string的一些細(xì)節(jié)剖析

    java string的一些細(xì)節(jié)剖析

    首先說明這里指的是Java中String的一些細(xì)節(jié)部分,需要的朋友可以參考
    2012-11-11
  • 計算兩個字符串最大公有子串

    計算兩個字符串最大公有子串

    本文主要介紹了計算兩個字符串最大公有子串的解決方案。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • Java實(shí)現(xiàn)讀取文章中重復(fù)出現(xiàn)的中文字符串

    Java實(shí)現(xiàn)讀取文章中重復(fù)出現(xiàn)的中文字符串

    本文主要介紹了Java實(shí)現(xiàn)讀取文章中重復(fù)出現(xiàn)的中文字符串的方法。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • Java JSON轉(zhuǎn)成List結(jié)構(gòu)數(shù)據(jù)

    Java JSON轉(zhuǎn)成List結(jié)構(gòu)數(shù)據(jù)

    這篇文章主要介紹了Java JSON轉(zhuǎn)成List結(jié)構(gòu)數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Mybatis中輸入輸出映射與動態(tài)Sql圖文詳解

    Mybatis中輸入輸出映射與動態(tài)Sql圖文詳解

    這篇文章主要給大家介紹了關(guān)于Mybatis中輸入輸出映射與動態(tài)Sql的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • 實(shí)時計算知多少?

    實(shí)時計算知多少?

    這篇文章對滑動窗口計數(shù)的概念和關(guān)鍵代碼做了較為詳細(xì)解釋,讓我們對實(shí)時計算這一概念有了更深的了解,需要的朋友可以參考下
    2015-07-07
  • Spring Cloud分布式定時器之ShedLock的實(shí)現(xiàn)

    Spring Cloud分布式定時器之ShedLock的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Cloud分布式定時器之ShedLock的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • spring security實(shí)現(xiàn)下次自動登錄功能過程解析

    spring security實(shí)現(xiàn)下次自動登錄功能過程解析

    這篇文章主要介紹了spring security實(shí)現(xiàn)記住我下次自動登錄功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論