Commit 5edbf066 by chenjunxiong

First Commit

parents
# Created by .ignore support plugin (hsz.mobi)
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
# 云存储系统安全升级:
# 云存储系统安全升级:
[TOC]
## 文件下载接口修改:
### 修改说明:
- 文件下载由原来重定向改为HTTP请求Responses.Body返回文件byte内容
- 这里解释下为什么我会选择重定向来做文件的获取:
- 假如我们通过```FastFileStorageClient```的接口来获取**100MB**的文件,文件会以比特流的方式储存在服务器内存中,考虑到带宽问题,这个文件在```HTTP```请求正常请求且客户端没读取超时的情况下会一直占用**100MB**内存,这也只是一个下载请求。若加上断点续传,这**100MB**的文件可能会被多次加载在内存里,以**BitComet**为例:
- **BitComet**在下载链接支持断点续传的情况下会默认创建**5**```HTTP```请求来获取该文件,分别是**0-20MB、20-40MB、40-60MB、60-80MB、80-100MB**
- 这时服务器会对应收到**请求头**```Range```分别为这些范围的```HTTP```请求,并且在不同的线程内通过```FastFileStorageClient```的接口来获取这**100MB**大小的文件,并加载到内存中,最后通过**请求头**```Range```参数来返回指定范围的比特流信息。
- 一个**100MB**的文件下载就让服务器消耗了**500MB**的内存,而且这也只是一个用户使用的情况下。
- 这时我发现现有的下载代码逻辑在生产上是完全无法使用的,根本承受不住轻微的并发,并且对服务器内存要求是极高的,迫切需要一种以**缓冲流方式**加载文件的方法来获取返回文件,恰巧```FastDFS``````fastdfs-nginx-module```支持,我就直接通过重定向的方法让```fastdfs-nginx-module```返回文件比特流,解决了文件下载的内存问题,并且减少了将完整文件加载至内存的过程减少了文件下载的等待时间。
- 原重定向的方法因FastDFS服务器支持断点续传,现断点续传需要通过代码实现
### HTTP1.1协议,断点续传(范围请求)技术说明:
- 以Chrome浏览器获取视频为例(只要遵循```HTTP1.1```协议即可):
- 浏览器首先发送一个简单GET请求,服务端返回200状态:
General:
```html
Request URL: http://localhost:20003/rangeTest
Request Method: GET
Status Code: 200
Remote Address: [::1]:20003
Referrer Policy: no-referrer-when-downgrade
```
Requset Headers:
```html
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
DNT: 1
Host: localhost:20003
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
```
Response Headers:
```html
Accept-Ranges: bytes
Content-Disposition: inline;filename="TestVideo.mp4"
Content-Length: 23508699
Content-Range: bytes 0-23508698/23508699
Content-Type: video/mp4
Date: Thu, 27 Jun 2019 01:52:35 GMT
ETag: TestVideo.mp4
Expires: Thu, 04 Jul 2019 01:52:35 GMT
Last-Modified: Fri, 15 Mar 2019 08:44:44 GMT
```
- 在这里浏览器判断服务器支不支持范围请求(断点续传)主要是看```Response Headers```是否有```Accept-Ranges```信息,且值不为```none```(```Accept-Ranges```**为禁止修改的HTTP头默认值为:bytes**),因此要实现断点续传功能首先服务器要在```Response Headers```返回```Accept-Ranges: bytes```告诉客户端服务端支持断点续传。
- 其中```Content-Type```、```Accept-Ranges```、```Content-Disposition```、```Content-Length```为文件有效信息:
- ```Content-Type: video/mp4```:文件类型为MP4
- ```Content-Disposition: inline;filename="TestVideo.mp4"```:以内联方式处理比特流、且文件名为TestVideo.mp4
- ```Content-Length: 23508699```:当前请求将返回的文件比特流大小
- ```Content-Range: bytes 0-23508698/23508699```:当前请求将返回文件完整的比特范围,这里是返回完整文件
- 经测试发现,Chrome浏览器及BitComet下载器在获取文件前都会做一次这样的简单GET请求来判断服务器是否支持范。**但是,值得注意的是,客户端并不会完整的接收完本次简单请求的比特流数据,而是在解析请求头中```Accept-Ranges```是否存在且值是否为```bytes```后马上主动断开连接,之后再根据客户端的设置进行范围请求,因此服务端无法悉知每一个过来的请求是获取完整文件还是仅仅为了识别服务器是否支持断点续传。**
- 经过一次简单GET请求后,客户端根据```Response Headers``````Accept-Ranges```知道服务端是否支持断点续传后会马上创建一个或多个GET请求,**但这些GET请求与第一次GET请求在```Requset Headers```有不同,并且服务端返回206状态**
General:
```html
Request URL: http://localhost:20003/rangeTest
Request Method: GET
Status Code: 206
Remote Address: [::1]:20003
Referrer Policy: no-referrer-when-downgrade
```
Requset Headers:
```
Accept-Encoding: identity;q=1, *;q=0
DNT: 1
Range: bytes=0-
Referer: http://localhost:20003/rangeTest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
```
Response Headers:
```
Accept-Ranges: bytes
Content-Disposition: inline;filename="TestVideo.mp4"
Content-Length: 23508699
Content-Range: bytes 0-23508698/23508699
Content-Type: video/mp4
Date: Thu, 27 Jun 2019 01:52:35 GMT
ETag: TestVideo.mp4
Expires: Thu, 04 Jul 2019 01:52:35 GMT
Last-Modified: Fri, 15 Mar 2019 08:44:44 GMT
```
- 根据以上请求头,关键点在于```Range```,该字段告诉服务端此次请求应该返回文件的比特流范围(```bytes=0-```表示从0开始直至文件比特数组下标结束,也就是完整文件,[详见](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Range))。
- 此时服务端应在解析完```Range: bytes=0-```后获取对应的文件比特流信息返回给客户端,并且响应状态为[206](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/206),假如所请求的范围不合法,那么服务器应响应状态[416](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/416)
- 若请求的范围合法,服务端应获取对应文件片段(也可能是完整文件),设置请求头```Content-Range``````Content-Length``````Content-Type```等头信息后返回比特流给客户端。
- 至此,一个基于```HTTP1.1```协议的范围请求(断点续传)结束了。
#### 业务逻辑说明:
1. 所有文件下载接口进来应先解析请求中的参数,从数据库获取```FileInfo```(含有文件大小、Hash值及FastDFS路径信息)及```UserFileInfo```(含有文件名)的信息:
* **若文件不存在则直接抛出```ResponseStatusException```异常,并设置```HttpStatus.NOT_FOUND```!**
2. 解析```Requset Headers```中的```Accept``````Range```等信息:
*```Range```不为空则调用```GenerateStorageClient.downloadFile```下载文件片段接口获取**文件片段比特流**,并且设置响应状态为[206](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/206)
* **若```Range```不为空且范围不合法则直接抛出```ResponseStatusException```异常,并设置```HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE```!**
*```Range```为空则调用```GenerateStorageClient.downloadFile```下载文件片段接口获取**完整文件比特流**,并且设置响应状态为[200](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/200)
3. 根据```Requset Headers```中的```Range```设置```Response Headers```
4. 根据```Requset Headers```中的```Accept```设置```Response Headers``````Content-Disposition```值([详见](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition)
5. 最后设置```Content-Length``````Content-Range``````Content-Type```并返回客户端比特流,在这里有一点需要注意下:
* 若客户端在服务端输出比特流未完成时主动断开,服务端会抛```java.io.IOException: 你的主机中的软件中止了一个已建立的连接。```异常信息,在这里我们统一捕获不处理,仅输出```warn```级别日志信息
#### 流程图:
```flow
start=>start: 客户端请求
end=>end: 请求结束
analyzeParams=>operation: 解析请求参数
getFileInfo=>operation: 获取文件信息
fileExist=>condition: 文件是否存在
error404=>operation: 抛出404异常
analyzeRange=>operation: 解析请求头Range
rangeIsEnpty=>condition: Range是否为空
rangeIsValid=>condition: Range是否有效
error416=>operation: 抛出416异常
getFile=>operation: 获取文件
getFileFragment=>operation: 获取文件片段
return200=>operation: 响应200状态并返回完整文件比特流
return206=>operation: 响应206状态并返回文件片段比特流
start->analyzeParams->getFileInfo->fileExist
fileExist(yes)->analyzeRange->rangeIsEnpty
fileExist(no)->error404->end
rangeIsEnpty(yes)->getFile->return200->end
rangeIsEnpty(no)->rangeIsValid
rangeIsValid(yes)->getFileFragment->return206->end
rangeIsValid(no)->error416->end
```
\ No newline at end of file
# 云存储第三阶段开发说明文档
# 云存储第三阶段开发说明文档
[TOC]
------
## 文档说明:
* **该文档为第三阶段开发计划的说明,具体任务安排、人员安排及开发周期会应实际开发需求有所变动,第三阶段开发分为三个阶段:**
* [准备阶段](#准备阶段:)
* [开发阶段](#开发阶段:)
* [测试阶段](#测试阶段:)
### 准备阶段:
* 现有功能完善:
* 文件下载接口修改(修改文件下载重定向为非重定向,不在暴露FastDFS地址)
* 完善文件hash比对机制
* 模块设计:
* 用户模块设计
* 文件管理模块设计
* 鉴权模块设计
* 模块搭建:
* 用户模块搭建
* 文件管理模块搭建
* 鉴权模块搭建
### 开发阶段:
* 后台管理系统开发:
* 用户文件信息查看(如:文件大小、格式等)
* 用户文件操作:
* 编辑、修改文件名
* 修改文件为共有或私有
* 删除文件
* 恢复在七天内删除的文件
* 修改文件过期时间
* 用户文件统计(文件为非删除状态及未过期)
* 文件数量统计
* 文件大小统计
* 文件类型统计
* 用户信息修改:
* 修改用户基本信息(如:密码、名称)
* 修改用户AccessKey/SecretKey
* 存储系统开发:
* 凭证系统
* 上传凭证(UploadToken)
* 下载凭证(DownloadToken)
* 管理凭证(AccessToken)
### 测试阶段:
* 存储系统接口测试
* 后台管理系统接口测试
---
## 任务安排:
### 准备阶段:
#### 现有功能完善:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------------- | ------------------ | -------- | ------------------------------------------------------------ |
| 文件下载接口修改 | 5 | 兰平雄 | 修改文件下载重定向为非重定向,<br />不在暴露FastDFS地址,<br />并减少断点续传不必要的内存消耗 |
| 完善文件hash值比对机制 | 3 | 兰平雄 | |
#### 模块设计:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------- | ------------------ | -------------- | -------------- |
| 用户模块设计 | 3 | 兰平雄、陈俊雄 | 含接口业务逻辑 |
| 文件管理模块设计 | 5 | 兰平雄、陈俊雄 | 含接口业务逻辑 |
| 鉴权模块设计 | 5 | 王德明 | 网关鉴权 |
#### 模块搭建:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------- | ------------------ | -------- | ---- |
| 用户模块搭建 | 2 | 兰平雄 | |
| 文件管理模块搭建 | 2 | 兰平雄 | |
| 鉴权模块搭建 | 2 | 王德明 | |
### 开发阶段:
#### 后台管理系统开发:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------- | ------------------ | -------- | ---- |
| 用户文件信息查看 | 3 | | |
| 用户文件操作 | 3 | | |
| 用户文件统计 | 4 | | |
| 用户信息修改 | 3 | | |
#### 存储系统开发:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| -------- | ------------------ | -------- | ---- |
| 凭证系统 | 7 | | |
---
## 开发文档:
* [文件下载接口修改]()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment