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

SpringBoot注解實現(xiàn)網(wǎng)絡(luò)限速

 更新時間:2026年02月18日 10:15:47   作者:OVO芙蘭朵  
本文介紹在 Spring Boot 3 中實現(xiàn)多維度網(wǎng)絡(luò)帶寬限速的完整方案,基于令牌桶算法手動實現(xiàn)核心邏輯,通過自定義攔截請求、包裝響應(yīng)流、控制輸出速率,實現(xiàn)對文件下載、視頻流等場景的精確速度控制,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

概述

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

為什么需要帶寬限速

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

場景一:文件下載服務(wù)

對于網(wǎng)盤或資源分發(fā)平臺,免費用戶限制在 200KB/s,VIP 用戶提升到 2MB/s,既能保障基礎(chǔ)體驗,又能激勵付費轉(zhuǎn)化。

場景二:視頻流媒體

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

場景三:API 接口保護

大數(shù)據(jù)量接口(如導(dǎo)出報表)如果沒有帶寬控制,單個請求可能占滿整個出口帶寬,影響其他用戶訪問。

核心原理:令牌桶算法

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

核心參數(shù)解析:

  • 桶容量(Capacity): 決定能承受多大突發(fā)流量。容量為 200KB 時,即使桶已滿,最多也只能連續(xù)發(fā)送 200KB 數(shù)據(jù),之后必須等待令牌補充。
  • 填充速率(Refill Rate): 決定長期平均傳輸速度。每秒補充 200KB 令牌,意味著平均速度就是 200KB/s。
  • 分塊大?。–hunk Size): 影響流量平滑度。將 8KB 數(shù)據(jù)拆分成 2KB×4 次寫入,每次寫入之間進行令牌檢查,比一次性寫入 8KB 更加平滑。

算法流程:

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

  • 計算距離上次補充的時間差
  • 根據(jù) 時間差 × 填充速率 計算新增令牌數(shù)
  • 更新桶中令牌數(shù)(不超過容量上限)

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

  • 檢查令牌是否足夠
  • 足夠:直接扣除令牌,發(fā)送數(shù)據(jù)
  • 不足:計算 (缺少令牌數(shù) / 填充速率) 得到等待時間,精確等待后發(fā)送

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

整體流程

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

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

為什么選擇 HandlerInterceptor

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

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

核心組件職責

組件

職責

@BandwidthLimit

聲明式注解,配置限速參數(shù)

BandwidthLimitInterceptor

攔截請求,解析注解,創(chuàng)建響應(yīng)包裝器

BandwidthLimitManager

管理多維度限速桶(全局/API/用戶/IP)

BandwidthLimitResponseWrapper

包裝 HttpServletResponse,替換 OutputStream

RateLimitedOutputStream

實現(xiàn)限速邏輯,包裝 TokenBucket

TokenBucket

令牌桶算法實現(xiàn)

BandwidthLimitHelper

從請求屬性中獲取包裝后的響應(yīng)對象

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

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

全局限速(GLOBAL)

所有請求共享同一個限速桶,適合保護服務(wù)器整體出口帶寬。例如設(shè)置 10MB/s 全局限制,即使有100個并發(fā)下載,總帶寬也不會超過 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)

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

@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ù)用戶標識(如請求頭 X-User-Id)進行限速,每個用戶獨立計算帶寬。配合 free 和 vip 參數(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ù)請求頭 X-User-Type 自動應(yīng)用 200KB/s 或 2MB/s 限速
}

IP 維度限速(IP)

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

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

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

1. 令牌桶核心算法

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

public synchronized void acquire(long permits) {
    // 1. 補充令牌
    refill();
 
    // 2. 計算等待時間
    if (tokens >= permits) {
        tokens -= permits;
        return;
    }
 
    long deficit = permits - tokens;
    long waitNanos = (deficit * 1_000_000_000L) / refillRate;
 
    // 3. 精確等待
    sleepNanos(waitNanos);
 
    // 4. 等待后消費
    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 {
    privatefinal TokenBucket sharedTokenBucket;  // 共享的令牌桶
 
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (limitedOutputStream == null && sharedTokenBucket != null) {
            // 使用共享 TokenBucket,確保多維度統(tǒng)計正確
            limitedOutputStream = new RateLimitedOutputStream(
                super.getOutputStream(),
                sharedTokenBucket,
                bandwidthBytesPerSecond
            );
        }
        return limitedOutputStream;
    }
}

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

攔截器在 preHandle 中創(chuàng)建響應(yīng)包裝器,存儲到 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)建包裝器并存儲
        BandwidthLimitResponseWrapper wrappedResponse =
            new BandwidthLimitResponseWrapper(response, bucket, bandwidthBytesPerSecond, chunkSize);
        request.setAttribute("BandwidthLimitWrappedResponse", wrappedResponse);
    }
    return true;
}

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

Controller 通過 BandwidthLimitHelper.getLimitedResponse() 獲取包裝后的響應(yī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ù)時自動限速
    limitedResponse.getOutputStream().write(data);
}

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

桶容量選擇

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

容量設(shè)置

突發(fā)能力

適用場景

速率 × 0.5

平滑,無突發(fā)

流量控制嚴格的場景

速率 × 1.0

允許 1 秒突發(fā)

默認推薦值

速率 × 2.0

允許 2 秒突發(fā)

需要良好首屏加載

// 注解配置
@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, capacityMultiplier = 1.0)

分塊大小選擇

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

帶寬

推薦分塊

理由

200 KB/s

1-4 KB

小分塊保證平滑

1 MB/s

4-8 KB

平衡平滑與性能

5 MB/s+

8-16 KB

減少系統(tǒng)調(diào)用開銷

// 自動計算(推薦)
@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, chunkSize = -1)
 
// 手動指定
@BandwidthLimit(value = 200, unit = BandwidthUnit.KB, chunkSize = 4096)

總結(jié)

本文基于令牌桶算法,通過 HandlerInterceptor + HttpServletResponseWrapper,在 Spring Boot 中實現(xiàn)了多維度帶寬限速。

支持全局/API/用戶/IP 四種限速維度,提供實時統(tǒng)計監(jiān)控,適用于API接口保護、文件下載、視頻流等場景。

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

相關(guān)文章

  • Java this關(guān)鍵字的引用詳解

    Java this關(guān)鍵字的引用詳解

    每個類中都有一個本類的this引用,類似:類名 this;實例對象時,this引用指向?qū)ο蟊旧恚渥钪饕淖饔檬亲岊愔械姆椒梢栽L問本類中的另外一個方法或?qū)傩?,因為調(diào)用一個方法或?qū)傩?非類方法/屬性)必須要有實例
    2022-03-03
  • Spring Boot 2和Redis例子實現(xiàn)過程解析

    Spring Boot 2和Redis例子實現(xiàn)過程解析

    這篇文章主要介紹了Spring Boot2發(fā)布與調(diào)用REST服務(wù)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下
    2019-11-11
  • java 輸入一個數(shù)字,反轉(zhuǎn)輸出這個數(shù)字的值(實現(xiàn)方法)

    java 輸入一個數(shù)字,反轉(zhuǎn)輸出這個數(shù)字的值(實現(xiàn)方法)

    下面小編就為大家?guī)硪黄猨ava 輸入一個數(shù)字,反轉(zhuǎn)輸出這個數(shù)字的值(實現(xiàn)方法)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 微信商家轉(zhuǎn)賬常見的一些問題匯總(附Java調(diào)用示例)

    微信商家轉(zhuǎn)賬常見的一些問題匯總(附Java調(diào)用示例)

    這篇文章主要介紹了微信商家轉(zhuǎn)賬常見的一些問題匯總,文中附Java調(diào)用示例,包括IP地址不允許調(diào)用接口、APPID不存在、未獲取轉(zhuǎn)賬場景、暫不支持展示用戶收款感知、未傳入完整且對應(yīng)的轉(zhuǎn)賬場景報備信息以及商戶運營賬戶資金不足等問題的解決步驟,需要的朋友可以參考下
    2025-12-12
  • Java中構(gòu)造、生成XML簡明教程

    Java中構(gòu)造、生成XML簡明教程

    這篇文章主要介紹了Java中構(gòu)造、生成XML簡明教程,本文通過dom4j包來完成,需要的朋友可以參考下
    2014-08-08
  • Spring如何實現(xiàn)管理事務(wù)

    Spring如何實現(xiàn)管理事務(wù)

    Spring通過編程式事務(wù)和聲明式事務(wù)管理來控制事務(wù)的邊界和行為,聲明式事務(wù)管理通過@Transactional注解實現(xiàn),提供了豐富的配置選項來控制事務(wù)的行為,如傳播行為、隔離級別、超時時間和回滾規(guī)則
    2024-11-11
  • MyBatis如何通過攔截修改SQL

    MyBatis如何通過攔截修改SQL

    這篇文章主要介紹了MyBatis如何通過攔截修改SQL問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • SpringBoot+layuimini實現(xiàn)左側(cè)菜單動態(tài)展示的示例代碼

    SpringBoot+layuimini實現(xiàn)左側(cè)菜單動態(tài)展示的示例代碼

    Layuimini是Layui的升級版,它是專業(yè)做后臺頁面的框架,而且是適合PC端和移動端,以下地址可以在PC端顯示,也可以在手機上顯示,只不過會做自適應(yīng),本文將給大家介紹了SpringBoot+layuimini實現(xiàn)左側(cè)菜單動態(tài)展示的方法,需要的朋友可以參考下
    2024-04-04
  • IntelliJ IDEA進行中文漢化的詳細教程(附圖文講解)

    IntelliJ IDEA進行中文漢化的詳細教程(附圖文講解)

    今天為大家?guī)淼氖?nbsp;IntelliJ IDEA 中文漢化教程以及中文插件包下載教程,經(jīng)常收到小伙伴在后臺給我留言,問 IDEA 怎么進行中文漢化,因為很多小伙伴是剛?cè)腴T Java,看到 IDEA 菜單全英文有些不太適應(yīng),需要的朋友可以參考下
    2024-12-12
  • java?Map集合中取鍵和值的4種方式舉例

    java?Map集合中取鍵和值的4種方式舉例

    Java中的Map是一種鍵值對存儲的數(shù)據(jù)結(jié)構(gòu),其中每個鍵都唯一,與一個值相關(guān)聯(lián),這篇文章主要給大家介紹了關(guān)于java?Map集合中取鍵和值的4種方式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01

最新評論

东山县| 乌审旗| 抚松县| 乐东| 临沧市| 大城县| 临西县| 桂平市| 怀来县| 咸阳市| 信宜市| 湾仔区| 望奎县| 呈贡县| 渑池县| 张家界市| 汉川市| 阳高县| 临沧市| 葫芦岛市| 河间市| 治县。| 灵宝市| 唐海县| 南澳县| 吐鲁番市| 武安市| 休宁县| 青冈县| 雷州市| 治多县| 渝北区| 北京市| 苍南县| 唐山市| 元阳县| 仁寿县| 礼泉县| 南涧| 绍兴市| 宁乡县|