共计 2505 个字符,预计需要花费 7 分钟才能阅读完成。
前言
在上一篇文章《面试官不讲武德》对 Java 高级程序猿死命摩擦 Http 协定 中,咱们有提到大文件下载和断点续传,本篇咱们就来开发一个多线程文件下载器,最初咱们用这个多线程下载器来冲破百度云盘下载的限速。
兄弟们看到这个题目可能会感觉是个题目党,为了解决疑虑,咱们先来看下最终的测试后果:
测试百度云下载的文件 46M,本人本地最大下载速度 2M
1. 单线程下载,总耗时: 603s
2. 多线程下载,50 个线程,总耗时:13s
测试后果,提速 46 倍,我还是太虚心了,只说提速 30 倍,此处咱们感觉应该有掌声(我听不到,还是点赞切实)
源码地址:https://gitee.com/silently9527/fast-download
喜爱请记得 star 哦
HTTP 协定 Range 申请头
Range 次要是针对只须要获取局部资源的范畴申请,通过指定 Range 即可告知服务器资源的指定范畴。格局: Range: bytes=start-end
比方:
获取字节范畴 5001-10000
Range: bytes=5001-10000
也能够指定开始地位不指定完结地位,示意获取开始地位之后的全副数据
Range: bytes=5001-
服务器接管到带有 Range
的申请,会在解决申请之后返回状态码为 206 Partial Content
的响应。
基于 Range 的个性,咱们就能够实现文件的多线程下载,文件的断点续传
筹备工作
本文咱们应用的 SpringMVC 中的 RestTemplate
;因为百度云的链接是 Https,所以咱们须要设置RestTemplate
绕过证书验证
- pom.xml
- 编写
RestTemplate
的结构器,以及绕过 https 的证书验证
- 在下载的过程中,咱们须要晓得以后下载的速度是多少,所以须要定义一个显示下载速度的接口
因为计算下载速度,咱们须要晓得每秒传输的字节数是多少,为了监控传输数据的过程,咱们须要理解 SpringMVC 中的接口ResponseExtractor
该接口只有一个办法,当客户端和服务器端连贯建设之后,会调用这个办法,咱们能够在这个办法中监控下载的速度。
DisplayDownloadSpeed
接口的形象实现AbstractDisplayDownloadSpeedResponseExtractor
- 整个我的项目次要波及到的类图
简略的文件下载器
这里应用的是 restTemplate 调用execute
, 先文件获取到字节数组, 再将字节数组间接写到指标文件。
这里咱们须要留神的点是: 这种形式会将文件的字节数组全副放入内存中, 及其耗费资源;咱们来看看如何实现。
- 创立
ByteArrayResponseExtractor
类继承AbstractDisplayDownloadSpeedResponseExtractor
- 调用
restTemplate.execute
执行下载,保留字节数据到文件中
- 测试下载 819M 的 idea
执行一段时间之后,咱们能够看到内存曾经应用了 800M 左右,所以这种形式只能应用于小文件的下载,如果咱们下载几 G 的大文件,内存必定是不够用的。至于下载工夫,因为文件太大也没有等下载实现就完结了程序。
单线程大文件下载
下面的形式只能下载小的文件,那大文件的下载咱们该用什么形式呢?咱们能够把流输入到文件而不是内存中。接下来咱们来实现咱们大文件的下载。
- 创立
FileResponseExtractor
类继承AbstractDisplayDownloadSpeedResponseExtractor
,把流输入到文件中
- 文件下载器,先把流输入到长期下载文件(xxxxx.download),下载实现后在重命名文件
- 测试下载 819M 的 idea
执行一段时间之后,咱们再看看下内存的应用状况,发现这种形式内存耗费较少,成果比拟现实,下载工夫:199s
多线程文件下载
如果服务器不限速的话,通常可能把本人本地的带宽给跑满,那么应用单线程下载就够了,然而如果遇到服务器限速,下载速度远小于本人本地的带宽,那么能够思考应用多线程下载。多线程咱们应用CompletableFuture
(能够参考文章 CompletableFuture 让你的代码免受阻塞之苦)。
实现多线程文件下载的根本流程:
- 首先咱们通过 Http 协定的 Head 办法获取到文件的总大小
- 而后依据设置的线程数均分文件的大小,计算每个线程的下载的字节数据开始地位和完结地位
- 开启线程,设置 HTTP 申请头 Range 信息,开始下载数据到临时文件
- 下载实现后把每个线程下载实现的临时文件合并成一个文件
实现代码如下:
- 开启 30 个线程测试下载 819M 的 idea
从执行的后果上来看,因为开启了 30 个线程同时在下载,内存的占用要比单线程耗费的多,然而也在承受范畴内,下载工夫:81s,速度晋升 2.5 倍,这是因为 idea 的下载服务器没有限速,本次多线程速度的晋升仅仅是在充沛的压迫本地的带宽,所以提醒的幅度不大。
单线程下载和对线程下载比照测试
因为百度云盘对单个线程的下载速度做了限度,大略是在 100kb,所以咱们应用百度云盘的下载链接,来测试多线程和单线程的下载速度。
- 测试 百度云盘中 46M 的文件的下载速度,本人本地最大下载速度 2M
- 获取文件的下载地址
留神:从浏览器中获取的链接须要先应用 URLDecode 解码,否则下载会失败,并且百度云盘文件的下载链接是有时效性的,过期后就不能在下载,须要从新生成下载链接
测试单线程下载文件
执行的后果能够看出,百度云对单线程的下载限速真的是丧心病狂,46M 的文件下载须要耗时:600s
测试多线程下载文件
为了充沛的压迫网速,找出最合适的线程数,所以测试了不同线程数的下载速度
线程数 | 下载总耗时 |
---|---|
10 | 60s |
20 | 30s |
30 | 21s |
40 | 15s |
50 | 13s |
从测试的后果上来看,对于本人的运行环境把线程数设置在 30 个左右比拟适合
文件断点续传如何实现,欢送在大家评论区说出本人的思路。
写到最初(点关注,不迷路)
文中或者会存在或多或少的有余、谬误之处,有倡议或者意见也十分欢送大家在评论交换。
最初,创作不易,请不要白嫖 ,心愿敌人们能够 点赞评论关注 三连,因为这些就是我分享的全副能源起源????
原创不易 转载请注明出处:
本文纯正用于学习