突破某度雲盤下載限速,提速30倍!想學?我教你啊

前言

在上一篇文章 《面試官不講武德》對Java初級程序猿死命摩擦Http協議 中,咱們有提到大文件下載和斷點續傳,本篇咱們就來開發一個多線程文件下載器,最後咱們用這個多線程下載器來突破百度雲盤下載的限速。git

兄弟們看到這個標題可能會以爲是個標題黨,爲了解決疑慮,咱們先來看下最終的測試結果:面試

測試百度雲下載的文件 46M,本身本地最大下載速度 2M數組

1. 單線程下載,總耗時: 603s

突破某度雲盤下載限速,提速30倍!想學?我教你啊

2. 多線程下載,50個線程,總耗時:13s

突破某度雲盤下載限速,提速30倍!想學?我教你啊

測試結果,提速46倍,我仍是太謙虛了,只說提速30倍,此處咱們以爲應該有掌聲(我聽不到,仍是點贊實在)瀏覽器

突破某度雲盤下載限速,提速30倍!想學?我教你啊

源碼地址: https://gitee.com/silently9527/fast-download 服務器

喜歡請記得star哦多線程


HTTP協議Range請求頭

Range主要是針對只須要獲取部分資源的範圍請求,經過指定Range便可告知服務器資源的指定範圍。格式: Range: bytes=start-endide

好比:
獲取字節範圍 5001-10000post

Range: bytes=5001-10000

也能夠指定開始位置不指定結束位置,表示獲取開始位置以後的所有數據測試

Range: bytes=5001-

服務器接收到帶有Range的請求,會在處理請求以後返回狀態碼爲206 Partial Content的響應。ui

基於Range的特性,咱們就能夠實現文件的多線程下載,文件的斷點續傳

準備工做

本文咱們使用的SpringMVC中的RestTemplate;因爲百度雲的連接是Https,因此咱們須要設置RestTemplate繞過證書驗證

  1. pom.xml

pom.xml

  1. 編寫RestTemplate的構造器,以及繞過https的證書驗證

RestTemplateBuilder

  1. 在下載的過程當中,咱們須要知道當前下載的速度是多少,因此須要定義一個顯示下載速度的接口

DisplayDownloadSpeed

由於計算下載速度,咱們須要知道每秒傳輸的字節數是多少,爲了監控傳輸數據的過程,咱們須要瞭解SpringMVC中的接口ResponseExtractor

ResponseExtractor

該接口只有一個方法,當客戶端和服務器端鏈接創建以後,會調用這個方法,咱們能夠在這個方法中監控下載的速度。

  1. DisplayDownloadSpeed接口的抽象實現 AbstractDisplayDownloadSpeedResponseExtractor

AbstractDisplayDownloadSpeedResponseExtractor

  1. 整個項目主要涉及到的類圖

突破某度雲盤下載限速,提速30倍!想學?我教你啊

簡單的文件下載器

這裏使用的是restTemplate調用execute, 先文件獲取到字節數組, 再將字節數組直接寫到目標文件。

這裏咱們須要注意的點是: 這種方式會將文件的字節數組所有放入內存中, 及其消耗資源;咱們來看看如何實現。

  1. 建立ByteArrayResponseExtractor類繼承AbstractDisplayDownloadSpeedResponseExtractor

ByteArrayResponseExtractor

  1. 調用restTemplate.execute執行下載,保存字節數據到文件中

突破某度雲盤下載限速,提速30倍!想學?我教你啊

  1. 測試下載819M的idea

突破某度雲盤下載限速,提速30倍!想學?我教你啊

突破某度雲盤下載限速,提速30倍!想學?我教你啊

執行一段時間以後,咱們能夠看到內存已經使用了800M左右,因此這種方式只能使用於小文件的下載,若是咱們下載幾G的大文件,內存確定是不夠用的。至於下載時間,由於文件太大也沒有等下載完成就結束了程序。

單線程大文件下載

上面的方式只能下載小的文件,那大文件的下載咱們該用什麼方式呢?咱們能夠把流輸出到文件而不是內存中。接下來咱們來實現咱們大文件的下載。

  1. 建立FileResponseExtractor類繼承AbstractDisplayDownloadSpeedResponseExtractor,把流輸出到文件中

突破某度雲盤下載限速,提速30倍!想學?我教你啊

  1. 文件下載器,先把流輸出到臨時下載文件(xxxxx.download),下載完成後在重命名文件

突破某度雲盤下載限速,提速30倍!想學?我教你啊

  1. 測試下載819M的idea

突破某度雲盤下載限速,提速30倍!想學?我教你啊

執行一段時間以後,咱們再看看下內存的使用狀況,發現這種方式內存消耗較少,效果比較理想,下載時間:199s

突破某度雲盤下載限速,提速30倍!想學?我教你啊

突破某度雲盤下載限速,提速30倍!想學?我教你啊

多線程文件下載

若是服務器不限速的話,一般可以把本身本地的帶寬給跑滿,那麼使用單線程下載就夠了,可是若是遇到服務器限速,下載速度遠小於本身本地的帶寬,那麼能夠考慮使用多線程下載。多線程咱們使用CompletableFuture(能夠參考文章 CompletableFuture讓你的代碼免受阻塞之苦)。

實現多線程文件下載的基本流程:

  1. 首先咱們經過Http協議的Head方法獲取到文件的總大小
  2. 而後根據設置的線程數均分文件的大小,計算每一個線程的下載的字節數據開始位置和結束位置
  3. 開啓線程,設置HTTP請求頭Range信息,開始下載數據到臨時文件
  4. 下載完成後把每一個線程下載完成的臨時文件合併成一個文件

完成代碼以下:

突破某度雲盤下載限速,提速30倍!想學?我教你啊

  1. 開啓30個線程測試下載819M的idea

突破某度雲盤下載限速,提速30倍!想學?我教你啊

突破某度雲盤下載限速,提速30倍!想學?我教你啊

突破某度雲盤下載限速,提速30倍!想學?我教你啊

從執行的結果上來看,由於開啓了30個線程同時在下載,內存的佔用要比單線程消耗的多,可是也在接受範圍內,下載時間:81s,速度提高2.5倍,這是由於idea的下載服務器沒有限速,本次多線程速度的提高僅僅是在充分的壓榨本地的帶寬,因此提示的幅度不大。

單線程下載和對線程下載對比測試

由於百度雲盤對單個線程的下載速度作了限制,大概是在100kb,因此咱們使用百度雲盤的下載連接,來測試多線程和單線程的下載速度。

  1. 測試 百度雲盤中 46M 的文件的下載速度,本身本地最大下載速度 2M

  2. 獲取文件的下載地址

突破某度雲盤下載限速,提速30倍!想學?我教你啊

注意:從瀏覽器中獲取的連接須要先使用URLDecode解碼,不然下載會失敗,而且百度雲盤文件的下載連接是有時效性的,過時後就不能在下載,須要從新生成下載連接

測試單線程下載文件

突破某度雲盤下載限速,提速30倍!想學?我教你啊

執行的結果能夠看出,百度雲對單線程的下載限速真的是喪心病狂, 46M的文件下載須要耗時: 600s

測試多線程下載文件

爲了充分的壓榨網速,找出最合適的線程數,因此測試了不一樣線程數的下載速度

線程數 下載總耗時
10 60s
20 30s
30 21s
40 15s
50 13s

從測試的結果上來看,對於本身的運行環境把線程數設置在30個左右比較合適

突破某度雲盤下載限速,提速30倍!想學?我教你啊


文件斷點續傳如何實現,歡迎在你們評論區說出本身的思路。

寫到最後(點關注,不迷路)

文中或許會存在或多或少的不足、錯誤之處,有建議或者意見也很是歡迎你們在評論交流。

最後,創做不易,請不要白嫖,但願朋友們能夠點贊評論關注三連,由於這些就是我分享的所有動力來源

相關文章
相關標籤/搜索