最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)網(wǎng)絡(luò)限速的方法詳解

 更新時(shí)間:2026年01月12日 08:50:19   作者:風(fēng)象南  
這篇文章主要為大家詳細(xì)介紹了Spring Boot 3 中實(shí)現(xiàn)多維度網(wǎng)絡(luò)帶寬限速的完整方案,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解下

概述

本文介紹在 Spring Boot 3 中實(shí)現(xiàn)多維度網(wǎng)絡(luò)帶寬限速的完整方案。基于令牌桶算法手動(dòng)實(shí)現(xiàn)核心邏輯,通過自定義 HandlerInterceptor 攔截請(qǐng)求、HttpServletResponseWrapper 包裝響應(yīng)流、RateLimitedOutputStream 控制輸出速率,實(shí)現(xiàn)對(duì)文件下載、視頻流等場景的精確速度控制。

為什么需要帶寬限速

帶寬限速與常見的 API 限流不同:限流控制的是請(qǐng)求次數(shù)(如每分鐘100次),而限速控制的是網(wǎng)絡(luò)帶寬(如每秒200KB)。在實(shí)際應(yīng)用中,帶寬限速有著重要的業(yè)務(wù)價(jià)值:

場景一:文件下載服務(wù) 對(duì)于網(wǎng)盤或資源分發(fā)平臺(tái),免費(fèi)用戶限制在 200KB/s,VIP 用戶提升到 2MB/s,既能保障基礎(chǔ)體驗(yàn),又能激勵(lì)付費(fèi)轉(zhuǎn)化。

場景二:視頻流媒體 不同清晰度對(duì)應(yīng)不同帶寬限制(480P 用 500KB/s,1080P 用 3MB/s),避免高碼率視頻占用過多服務(wù)器帶寬。

場景三:API 接口保護(hù) 大數(shù)據(jù)量接口(如導(dǎo)出報(bào)表)如果沒有帶寬控制,單個(gè)請(qǐng)求可能占滿整個(gè)出口帶寬,影響其他用戶訪問。

核心原理:令牌桶算法

令牌桶算法是流量控制的經(jīng)典方案,其思想非常直觀:想象一個(gè)桶,系統(tǒng)以固定速率向桶中放入令牌,請(qǐng)求數(shù)據(jù)時(shí)必須從桶中取走對(duì)應(yīng)數(shù)量的令牌。

核心參數(shù)解析:

1. 桶容量(Capacity):決定能承受多大突發(fā)流量。容量為 200KB 時(shí),即使桶已滿,最多也只能連續(xù)發(fā)送 200KB 數(shù)據(jù),之后必須等待令牌補(bǔ)充。

2. 填充速率(Refill Rate):決定長期平均傳輸速度。每秒補(bǔ)充 200KB 令牌,意味著平均速度就是 200KB/s。

3. 分塊大?。–hunk Size):影響流量平滑度。將 8KB 數(shù)據(jù)拆分成 2KB×4 次寫入,每次寫入之間進(jìn)行令牌檢查,比一次性寫入 8KB 更加平滑。

算法流程:

發(fā)送數(shù)據(jù)前:

1. 計(jì)算距離上次補(bǔ)充的時(shí)間差

2. 根據(jù) 時(shí)間差 × 填充速率 計(jì)算新增令牌數(shù)

3. 更新桶中令牌數(shù)(不超過容量上限)

發(fā)送數(shù)據(jù)時(shí):

1. 檢查令牌是否足夠

2. 足夠:直接扣除令牌,發(fā)送數(shù)據(jù)

3. 不足:計(jì)算 (缺少令牌數(shù) / 填充速率) 得到等待時(shí)間,精確等待后發(fā)送

技術(shù)設(shè)計(jì)

整體流程

本方案采用攔截器模式,在請(qǐng)求處理的早期階段完成限速組件的初始化,通過請(qǐng)求屬性傳遞包裝后的響應(yīng)對(duì)象。

請(qǐng)求流程:
┌─────────────────────────────────────────────────────────────────────┐
│ 1. DispatcherServlet 分發(fā)請(qǐng)求                                       │
└─────────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────────┐
│ 2. BandwidthLimitInterceptor.preHandle()                            │
│    - 解析 @BandwidthLimit 注解                                      │
│    - 從 BandwidthLimitManager 獲取共享 TokenBucket                   │
│    - 創(chuàng)建 BandwidthLimitResponseWrapper 并存入 request attribute    │
└─────────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────────┐
│ 3. Controller 處理請(qǐng)求                                              │
│    - 通過 BandwidthLimitHelper.getLimitedResponse() 獲取包裝后的響應(yīng) │
│    - 向響應(yīng)流寫入數(shù)據(jù)(自動(dòng)觸發(fā)限速)                                │
└─────────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────────┐
│ 4. BandwidthLimitInterceptor.afterCompletion()                      │
│    - 清理資源,關(guān)閉流                                                │
└─────────────────────────────────────────────────────────────────────┘

為什么選擇 HandlerInterceptor

在 Spring Boot 中實(shí)現(xiàn)請(qǐng)求處理,有兩種常見方式:Filter 和 HandlerInterceptor。本方案選擇 HandlerInterceptor 的關(guān)鍵原因是:注解解析需要 HandlerMethod 對(duì)象。

Filter 在 DispatcherServlet 之前執(zhí)行,此時(shí)還沒有確定具體的處理方法,無法獲取方法上的 @BandwidthLimit 注解。而 HandlerInterceptor 在處理器確定后執(zhí)行,可以通過 HandlerMethod 精確獲取方法級(jí)別和類級(jí)別的注解信息。

核心組件職責(zé)

組件職責(zé)
@BandwidthLimit聲明式注解,配置限速參數(shù)
BandwidthLimitInterceptor攔截請(qǐng)求,解析注解,創(chuàng)建響應(yīng)包裝器
BandwidthLimitManager管理多維度限速桶(全局/API/用戶/IP)
BandwidthLimitResponseWrapper包裝 HttpServletResponse,替換 OutputStream
RateLimitedOutputStream實(shí)現(xiàn)限速邏輯,包裝 TokenBucket
TokenBucket令牌桶算法實(shí)現(xiàn)
BandwidthLimitHelper從請(qǐng)求屬性中獲取包裝后的響應(yīng)對(duì)象

多維度限速實(shí)現(xiàn)

本方案支持四種限速維度,滿足不同業(yè)務(wù)場景需求:

全局限速(GLOBAL)

所有請(qǐng)求共享同一個(gè)限速桶,適合保護(hù)服務(wù)器整體出口帶寬。例如設(shè)置 10MB/s 全局限制,即使有100個(gè)并發(fā)下載,總帶寬也不會(huì)超過 10MB/s。

@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, type = LimitType.GLOBAL)
@GetMapping("/download/global")
public void downloadGlobal(HttpServletResponse response) throws IOException {
    HttpServletResponse limitedResponse = BandwidthLimitHelper.getLimitedResponse(request, response);
    // 寫入數(shù)據(jù)...
}

API 維度限速(API)

每個(gè)接口路徑獨(dú)立限速,不同接口的流量互不影響。/api/file/download 限制 500KB/s,/api/video/stream 限制 2MB/s,兩個(gè)接口可以同時(shí)達(dá)到各自的速度上限。

@BandwidthLimit(value = 500, unit = BandwidthUnit.KB, type = LimitType.API)
@GetMapping("/download/file")
public void downloadFile(HttpServletResponse response) throws IOException {
    // 文件下載邏輯
}

@BandwidthLimit(value = 2048, unit = BandwidthUnit.KB, type = LimitType.API)
@GetMapping("/stream/video")
public void streamVideo(HttpServletResponse response) throws IOException {
    // 視頻流邏輯
}

用戶維度限速(USER)

根據(jù)用戶標(biāo)識(shí)(如請(qǐng)求頭 X-User-Id)進(jìn)行限速,每個(gè)用戶獨(dú)立計(jì)算帶寬。配合 freevip 參數(shù),可實(shí)現(xiàn)差異化服務(wù):

@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, type = LimitType.USER,
                free = 200, vip = 2048)
@GetMapping("/download/user")
public void downloadByUser(@RequestHeader("X-User-Type") String userType,
                           HttpServletResponse response) throws IOException {
    // 根據(jù)請(qǐng)求頭 X-User-Type 自動(dòng)應(yīng)用 200KB/s 或 2MB/s 限速
}

IP 維度限速(IP)

根據(jù)客戶端 IP 地址限速,防止單個(gè) IP 占用過多帶寬。支持代理環(huán)境下的 IP 獲?。╔-Forwarded-For、X-Real-IP)。

@BandwidthLimit(value = 300, unit = BandwidthUnit.KB, type = LimitType.IP)
@GetMapping("/download/ip")
public void downloadByIp(HttpServletResponse response) throws IOException {
    // 每個(gè)獨(dú)立 IP 限制 300KB/s
}

關(guān)鍵代碼實(shí)現(xiàn)

1. 令牌桶核心算法

TokenBucket 的核心在于精確的時(shí)間計(jì)算和令牌補(bǔ)充。使用 System.nanoTime() 獲取納秒級(jí)時(shí)間戳,確保高精度速率控制。

public synchronized void acquire(long permits) {
    // 1. 補(bǔ)充令牌
    refill();

    // 2. 計(jì)算等待時(shí)間
    if (tokens >= permits) {
        tokens -= permits;
        return;
    }

    long deficit = permits - tokens;
    long waitNanos = (deficit * 1_000_000_000L) / refillRate;

    // 3. 精確等待
    sleepNanos(waitNanos);

    // 4. 等待后消費(fèi)
    tokens = 0;
}

private void refill() {
    long now = System.nanoTime();
    long elapsedNanos = now - lastRefillTime;
    long newTokens = (elapsedNanos * refillRate) / 1_000_000_000L;
    tokens = Math.min(capacity, tokens + newTokens);
    lastRefillTime = now;
}

2. 響應(yīng)包裝器

HttpServletResponseWrapper 是 Servlet 規(guī)范提供的響應(yīng)包裝基類,通過覆蓋 getOutputStream() 方法返回自定義的限速輸出流。

public class BandwidthLimitResponseWrapper extends HttpServletResponseWrapper {
    private final TokenBucket sharedTokenBucket;  // 共享的令牌桶

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (limitedOutputStream == null && sharedTokenBucket != null) {
            // 使用共享 TokenBucket,確保多維度統(tǒng)計(jì)正確
            limitedOutputStream = new RateLimitedOutputStream(
                super.getOutputStream(),
                sharedTokenBucket,
                bandwidthBytesPerSecond
            );
        }
        return limitedOutputStream;
    }
}

3. 攔截器獲取包裝響應(yīng)

攔截器在 preHandle 中創(chuàng)建響應(yīng)包裝器,存儲(chǔ)到 request attribute,Controller 通過 BandwidthLimitHelper 獲取。

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    BandwidthLimit annotation = findAnnotation(handler);
    if (annotation != null) {
        // 從 Manager 獲取共享 TokenBucket
        TokenBucket bucket = limitManager.getBucket(type, key, capacity, rate);

        // 創(chuàng)建包裝器并存儲(chǔ)
        BandwidthLimitResponseWrapper wrappedResponse =
            new BandwidthLimitResponseWrapper(response, bucket, bandwidthBytesPerSecond, chunkSize);
        request.setAttribute("BandwidthLimitWrappedResponse", wrappedResponse);
    }
    return true;
}

4. Controller 獲取限速響應(yīng)

Controller 通過 BandwidthLimitHelper.getLimitedResponse() 獲取包裝后的響應(yīng),所有寫入操作都會(huì)自動(dòng)限速。

@GetMapping("/download/global")
public void downloadGlobal(HttpServletRequest request, HttpServletResponse response) throws IOException {
    HttpServletResponse limitedResponse = BandwidthLimitHelper.getLimitedResponse(request, response);

    limitedResponse.setContentType("application/octet-stream");
    limitedResponse.setHeader("Content-Disposition", "attachment; filename=test.bin");

    // 寫入數(shù)據(jù)時(shí)自動(dòng)限速
    limitedResponse.getOutputStream().write(data);
}

參數(shù)調(diào)優(yōu)指南

桶容量選擇

容量決定突發(fā)流量承受能力:

容量設(shè)置突發(fā)能力適用場景
速率 × 0.5平滑,無突發(fā)流量控制嚴(yán)格的場景
速率 × 1.0允許 1 秒突發(fā)默認(rèn)推薦值
速率 × 2.0允許 2 秒突發(fā)需要良好首屏加載
// 注解配置
@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, capacityMultiplier = 1.0)

分塊大小選擇

分塊大小影響流量平滑度,經(jīng)驗(yàn)公式:chunkSize = bandwidth / 50

帶寬推薦分塊理由
200 KB/s1-4 KB小分塊保證平滑
1 MB/s4-8 KB平衡平滑與性能
5 MB/s+8-16 KB減少系統(tǒng)調(diào)用開銷
// 自動(dòng)計(jì)算(推薦)
@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, chunkSize = -1)

// 手動(dòng)指定
@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, chunkSize = 4096)

總結(jié)

本文基于令牌桶算法,通過 HandlerInterceptor + HttpServletResponseWrapper,在 Spring Boot 中實(shí)現(xiàn)了多維度帶寬限速。支持全局/API/用戶/IP 四種限速維度,提供實(shí)時(shí)統(tǒng)計(jì)監(jiān)控,適用于API接口保護(hù)、文件下載、視頻流等場景。

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)網(wǎng)絡(luò)限速的方法詳解的文章就介紹到這了,更多相關(guān)SpringBoot網(wǎng)絡(luò)限速內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot實(shí)現(xiàn)訪問多個(gè)redis庫

    springboot實(shí)現(xiàn)訪問多個(gè)redis庫

    這篇文章主要介紹了springboot實(shí)現(xiàn)訪問多個(gè)redis庫方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java遠(yuǎn)程調(diào)用接口、URL的方式代碼

    java遠(yuǎn)程調(diào)用接口、URL的方式代碼

    我們都知道接口有自己本地的,也有遠(yuǎn)程別人寫好的,而調(diào)用遠(yuǎn)程接口的就需要使用遠(yuǎn)程調(diào)用啦,這篇文章主要給大家介紹了關(guān)于java遠(yuǎn)程調(diào)用接口、URL的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Java核心技術(shù)之反射

    Java核心技術(shù)之反射

    本文非常詳細(xì)的講解了java反射的相關(guān)資料,java反射在現(xiàn)今的使用中很頻繁,希望此文可以幫大家解答疑惑,可以幫助大家理解
    2021-11-11
  • SpringBoot項(xiàng)目構(gòu)建Maven標(biāo)簽及屬性用法詳解

    SpringBoot項(xiàng)目構(gòu)建Maven標(biāo)簽及屬性用法詳解

    在?Spring?Boot?項(xiàng)目中,Maven?是最常用的構(gòu)建工具之一,本文將詳細(xì)介紹?Maven?依賴管理中的主要標(biāo)簽及其使用方法,幫助開發(fā)者更好地理解和使用?Maven?構(gòu)建工具,感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • 從零開始Java實(shí)現(xiàn)Parser?Combinator

    從零開始Java實(shí)現(xiàn)Parser?Combinator

    這篇文章主要為大家介紹了從零開始Java實(shí)現(xiàn)Parser?Combinator過程及原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 學(xué)習(xí)Java多線程之volatile域

    學(xué)習(xí)Java多線程之volatile域

    這篇文章主要為大家詳細(xì)介紹了Java多線程之volatile域,Java 語言提供了一種稍弱的同步機(jī)制,即volatile,本文為大家解答,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 在Java中自由塊的執(zhí)行順序

    在Java中自由塊的執(zhí)行順序

    java中的自由塊分為靜態(tài)的自由塊和非靜態(tài)的自由塊。非靜態(tài)自由塊的執(zhí)行時(shí)間是:在執(zhí)行構(gòu)造函數(shù)之前。靜態(tài)自由塊的執(zhí)行時(shí)間是:class文件加載時(shí)執(zhí)行。
    2013-04-04
  • SpringBoot接入華為云短信SDK的流程步驟

    SpringBoot接入華為云短信SDK的流程步驟

    這篇文章主要介紹了華為云短信服務(wù)的主要特點(diǎn)和使用步驟,包括開通服務(wù)、控制臺(tái)配置和SpringBoot項(xiàng)目集成,需要的朋友可以參考下
    2026-01-01
  • Java設(shè)計(jì)模式之責(zé)任鏈模式(Chain of Responsibility模式)介紹

    Java設(shè)計(jì)模式之責(zé)任鏈模式(Chain of Responsibility模式)介紹

    這篇文章主要介紹了Java設(shè)計(jì)模式之責(zé)任鏈模式(Chain of Responsibility模式)介紹,本文講解了如何使用責(zé)任鏈模式,并給出了4種使用實(shí)例,需要的朋友可以參考下
    2015-03-03
  • Java字符串格式化功能?String.format用法詳解

    Java字符串格式化功能?String.format用法詳解

    String類的format()方法用于創(chuàng)建格式化的字符串以及連接多個(gè)字符串對(duì)象,熟悉C語言的同學(xué)應(yīng)該記得C語言的sprintf()方法,兩者有類似之處,format()方法有兩種重載形式
    2024-09-09

最新評(píng)論

台东县| 刚察县| 高青县| 鞍山市| 富锦市| 盐城市| 青阳县| 文昌市| 长宁区| 衡水市| 莎车县| 东方市| 策勒县| 高陵县| 长白| 郁南县| 永清县| 岳西县| 保德县| 江口县| 闽侯县| 澜沧| 日照市| 子长县| 沂水县| 曲麻莱县| 井研县| 岢岚县| 百色市| 客服| 舟山市| 阳谷县| 亚东县| 喀喇沁旗| 长子县| 逊克县| 上犹县| 道真| 贵定县| 泸定县| 罗山县|