springboot下載接口限速功能實(shí)現(xiàn)
當(dāng)然可以!我們來結(jié)合你提供的代碼和限速邏輯,詳細(xì)說明整個(gè)“下載限速”功能是如何實(shí)現(xiàn)的。
?? 一、整體目標(biāo)
我們要實(shí)現(xiàn)的功能是:
限制每個(gè)用戶的下載速度(例如1MB/s),并根據(jù)當(dāng)前并發(fā)下載用戶數(shù)動(dòng)態(tài)調(diào)整限速值。
?? 二、涉及的主要類/方法
| 類/方法 | 功能 |
|---|---|
FileUtil.limitDownloadSpeed(...) | 核心限速方法,控制每秒發(fā)送的數(shù)據(jù)量 |
download(...) | 下載入口,獲取文件路徑、設(shè)置響應(yīng)頭等 |
limitReadFile(...) | 調(diào)用限速方法執(zhí)行下載 |
| Redis 操作 | 統(tǒng)計(jì)并發(fā)下載數(shù),用于動(dòng)態(tài)限速 |
? 三、核心流程圖解(簡(jiǎn)化)
客戶端發(fā)起請(qǐng)求
↓
download(...) 方法被調(diào)用
↓
從 Redis 增加并發(fā)數(shù) DOWNLOAD_CONCURRENT_KEY
↓
根據(jù)并發(fā)數(shù)計(jì)算限速值(getDownloadSpeedLimit)
↓
調(diào)用 limitReadFile(...) 開始下載文件
↓
limitReadFile(...) 內(nèi)部調(diào)用 FileUtil.limitDownloadSpeed(...)
↓
讀取文件內(nèi)容 → 分段寫入輸出流 → 控制每秒發(fā)送的數(shù)據(jù)量
↓
下載完成或客戶端斷開連接
↓
finally 中減少 Redis 的并發(fā)數(shù)?? 四、關(guān)鍵代碼詳解
1?? 設(shè)置并發(fā)數(shù) + 獲取限速值(download(...) 方法中)
// 增加并發(fā)計(jì)數(shù)器 Long currentConcurrent = redisTemplate.opsForValue().increment(DOWNLOAD_CONCURRENT_KEY); // 更新過期時(shí)間 redisTemplate.expire(DOWNLOAD_CONCURRENT_KEY, EXPIRE_TIME_IN_SECONDS, TimeUnit.SECONDS); // 計(jì)算限速值 int speedLimit = getDownloadSpeedLimit(currentConcurrent.intValue());
increment(...):將 Redis 中的鍵值增加 1,表示有新的下載開始。expire(...):為這個(gè) key 設(shè)置過期時(shí)間,防止僵尸數(shù)據(jù)。getDownloadSpeedLimit(...):根據(jù)當(dāng)前并發(fā)數(shù)計(jì)算單個(gè)用戶的限速值。
2?? 限速策略函數(shù) getDownloadSpeedLimit(...)
private int getDownloadSpeedLimit(int concurrentCount) {
int totalBandwidth = 1024 * 1024 * 5; // 總帶寬 5MB/s
int perUserSpeed = totalBandwidth / Math.max(1, concurrentCount);
return Math.max(perUserSpeed, 1024 * 50); // 最低限速 50KB/s
}- 如果當(dāng)前只有 1 個(gè)用戶下載,那他可以使用全部 5MB/s;
- 如果有 5 個(gè)用戶同時(shí)下載,每人最多只能用到 1MB/s;
- 即使并發(fā)數(shù)很多,也保證最低 50KB/s,避免卡死。
3?? 實(shí)際限速邏輯(FileUtil.limitDownloadSpeed(...))
public static void limitDownloadSpeed(InputStream in, OutputStream out, int bytesPerSecond) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE]; // 默認(rèn)是 1024 字節(jié)
int bytesRead;
long bytesSent = 0;
long startTime = System.currentTimeMillis();
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
bytesSent += bytesRead;
if (bytesSent >= bytesPerSecond) {
long elapsedTime = System.currentTimeMillis() - startTime;
if (elapsedTime < 1000) {
Thread.sleep(1000 - elapsedTime);
}
bytesSent = 0;
startTime = System.currentTimeMillis();
}
}
}這段代碼的核心邏輯是:
- 每次從輸入流讀取一塊數(shù)據(jù)(默認(rèn) 1KB);
- 將這塊數(shù)據(jù)寫入輸出流(即發(fā)給客戶端);
- 累計(jì)已發(fā)送的字節(jié)數(shù);
- 如果累計(jì)發(fā)送的數(shù)據(jù)超過設(shè)定的
bytesPerSecond(如 1MB),就判斷這一秒還沒過去,那么線程休眠剩余時(shí)間; - 重置計(jì)數(shù)器和開始時(shí)間,進(jìn)入下一輪循環(huán)。
示例:限速 1MB/s
- 第一次循環(huán):
- 讀取了 1024 × 1000 = 1MB 數(shù)據(jù);
- 發(fā)送完后發(fā)現(xiàn)只用了 500ms;
- 休眠 500ms;
- 清空計(jì)數(shù)器,重新開始下一秒的限速。
這樣就能保證 每秒最多發(fā)送 1MB 數(shù)據(jù)。
?? 五、如何做到“并發(fā)越多,限速越小”?
舉個(gè)例子:
| 并發(fā)數(shù) | 總帶寬(假設(shè)) | 每人可用帶寬 |
|---|---|---|
| 1 | 5MB/s | 5MB/s |
| 2 | 5MB/s | 2.5MB/s |
| 5 | 5MB/s | 1MB/s |
| 10 | 5MB/s | 500KB/s |
| 100 | 5MB/s | 50KB/s(最小限制) |
通過這種方式,系統(tǒng)會(huì)自動(dòng)平衡所有用戶的下載速度,不會(huì)因?yàn)槟骋粋€(gè)用戶占用過多帶寬而導(dǎo)致其他用戶下載很慢。
?? 六、完整流程總結(jié)
| 步驟 | 描述 |
|---|---|
| 1. 客戶端請(qǐng)求下載 | 請(qǐng)求 /file/download/[code] |
| 2. 服務(wù)器記錄并發(fā)數(shù) | 使用 Redis INCR 增加并發(fā)計(jì)數(shù) |
| 3. 計(jì)算限速值 | 根據(jù)并發(fā)數(shù)平均分配總帶寬 |
| 4. 執(zhí)行限速下載 | 使用 limitDownloadSpeed(...) 控制每秒發(fā)送的字節(jié)數(shù) |
| 5. 客戶端中斷或下載完成 | 使用 FINALLY 減少 Redis 中的并發(fā)數(shù) |
| 6. 自動(dòng)清理 | Redis key 設(shè)置了過期時(shí)間,防止數(shù)據(jù)殘留 |
? 七、優(yōu)點(diǎn)總結(jié)
| 特性 | 是否支持 | 說明 |
|---|---|---|
| 靜態(tài)限速 | ? 是 | 可以為每個(gè)用戶固定限速 |
| 動(dòng)態(tài)限速 | ? 是 | 根據(jù)并發(fā)數(shù)自動(dòng)調(diào)整限速 |
| Redis 支持 | ? 是 | 實(shí)現(xiàn)并發(fā)統(tǒng)計(jì) |
| 異常安全 | ? 是 | finally 中釋放資源 |
| 可擴(kuò)展性強(qiáng) | ? 是 | 可加入 VIP 用戶、IP 限速等功能 |
?? 八、可選優(yōu)化建議(進(jìn)階)
| 優(yōu)化點(diǎn) | 說明 |
|---|---|
| 緩沖區(qū)增大 | 把 BUFFER_SIZE 改成 64KB 或 128KB 提升性能 |
| 更精細(xì)限速 | 每 100ms 控制一次限速,而不是每秒 |
| VIP 用戶優(yōu)先 | 不同用戶組使用不同限速策略 |
| 斷點(diǎn)續(xù)傳 | 支持 Range 請(qǐng)求頭,允許暫停繼續(xù)下載 |
| 日志記錄 | 記錄每次下載的 IP、速度、時(shí)長(zhǎng)等信息 |
| 帶寬監(jiān)控 | 顯示實(shí)時(shí)帶寬使用情況、并發(fā)數(shù)等 |
?? 九、結(jié)語
你現(xiàn)在擁有的是一套完整的、可落地的 “并發(fā)感知型下載限速系統(tǒng)”,它具備以下特點(diǎn):
- ? 支持靜態(tài)限速
- ? 支持動(dòng)態(tài)限速(基于并發(fā))
- ? 使用 Redis 統(tǒng)計(jì)并發(fā)
- ? 限速邏輯清晰高效
- ? 安全可靠,異常處理完善
如果你希望我?guī)湍氵M(jìn)一步擴(kuò)展功能,比如:
- 支持 VIP 用戶限速更高
- 加入日志記錄模塊
- 實(shí)現(xiàn)斷點(diǎn)續(xù)傳
- 添加帶寬監(jiān)控頁面
到此這篇關(guān)于springboot下載接口限速功能實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)springboot下載限速內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Cloud中各組件超時(shí)總結(jié)
在大家學(xué)習(xí)spring cloud的時(shí)候組件是必不可少的一部分,下面這篇文章主要給大家介紹了關(guān)于Spring Cloud中各組件超時(shí)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-11-11

