Skip to content

OSS存储平台项目总结

Posted on:2023年5月30日 at 06:23

前言

用于记录该项目主要功能的部分实现与后续在面试中被问到的问题

上传

什么是md5?

MD5消息摘要算法(MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

webworker计算md5

计算md5时间很久,这段时间怎么办?(不知道怎么答)

弄个加载动画(?

Rust可以优化(不会

大文件切片上传

前置流程

计算完md5后对后端发起post请求,询问文件是否上传过,此时可能会得到三种结果:

  1. 未上传
  2. 部分上传,分块上传逻辑
  3. 已上传,秒传逻辑

并行上传切片

上传并发数默认是3,上传切片大小默认是1M。从理论层面来说:

第一,Chrome 对于同一个域名的 http1.1 请求来说,最大支持的并发请求数是6,如果单请求在整个通路上有最大速度限制,那调大这个并发数就是有意义的;

第二,切片1MB,对于一个5000MB的视频来说就切了5000片,如果网速足够快的话 http 建立连接的时间可能都比传输速度长。

进一步思考:并发数如果调到6,就相当于这个域名下所有请求都被阻塞了,如果还有其他依赖这个域名的请求就会很慢影响用户体验。如果切片大小很大,那在差网络情况下,例如 200KB/s,切片大小32MB,用户好不容易传到10MB了因为网络问题失败了,那就要重试等待很久,也影响用户体验。

解决

  1. 首先进行埋点,在当时的情况尽可能多的获得用户的网速层面,来定义默认配置行为
  2. 在用户上传前检测网络情况,对于网络情况好的用户配置更高的切片大小

注意点

  1. 分片大小会影响续传,分片大小变了,下次就会续传不了。所以只设置了跨度较大的8M和32M两个大小
  2. 目前6个,会不会有其他请求需要用到该域名?预留一个机会给列出文件等请求操作,也就是设置5并发,等域名扩展再搞多并发

新思路

如果并发数量能够根据用户的实时网速灵活变化,当网速慢时并发数量低,网速快时并发数量高就能解决上述问题了

详细方案

我们可以从BBR算法和TCP的拥塞策略中借鉴思路

策略目标:根据用户实时网速动态控制并发数量保证上传成功率,并尽可能利用用户带宽 基于上述目标优化并发上传的策略:

慢启动

当刚刚开始上传时,不能一开始将并发数量(concurrency)设置得很大,这样如果用户网络状况差容易一开始就造成上传超时,我们在开始先将 concurrency =2,然后根据传输情况来逐步扩大concurrency来适应当前的网络状态,直到达到慢启动的门限阈值(ssthresh),步骤如下:

  1. 初始化设置 concurrency=2concurrency = 16,并发传输两个分片
  2. 每成功上传一个包,就会将concurrency加1
  3. 当初始两个包上传成功后,即完成第一轮上传时concurrency为4
  4. concurrency< ssthresh且每个分片都成功上传时,concurrency按每轮concurrency *2指数级上升
  5. concurrency >= ssthresh或发生上传超时,则认为当前并发量超过了网络传输速度,发生了网络拥塞,慢启动结束,进入拥塞避免状态。
拥塞避免

concurrency >= ssthresh即并发数大于等于阈值时,有可能还未到网络传输速度的上限,这个时候需要进一步通过一个缓慢的调节过程来进行适配。

  1. 当concurrency >= ssthresh时,进入拥塞避免状态,ssthresh初始值设置为16
  2. 每轮concurrency个分片都上传成功后,并发数量加1,即设置 concurrency=concurrency + 1,一但发现丢包和超时重传,则进入拥塞处理状态
拥塞处理

当分片上传出现了超时失败时,会将失败的包塞到待上传队列的队尾,进入拥塞处理状态。

  1. 进入拥塞处理状态会将concurrency = concurrency * 0.75,也就是将当前并发数量减小25%,然后设置ssthresh = concurrency
  2. 降低concurrency的实现方式是,以每收到4个分片记为一组,前三个分片收到上传结果,每个分片会向上传队列里加进去1个待上传分片,收到第四个分片的上传结果后不向上传队列加待上传分片。
总结

通过这种策略实现了分片上传的并发数量根据用户的实时网速灵活变化。

高并发情况等待队列处理

秒传

网络条件很差怎么办?

调整分片大小

自定义Hooks

React Hooks学习记录 (homurafield.netlify.app)

Antd组件二次封装

样式

由于有UI给出的确立好的设计稿,表单、列表等组件样式完全一致。可以直接在全局中使用id选择器加强权重的方式来避免 !impoatant 的多次出现。

类型扩展

像表格这类数据的内容类型肯定都是由外部确立传递,因此要使用泛型。

竞态问题

图片位

网络正常的情况下直接请求展示数据即可。但当网络不稳定时可能会出现查询项和展示结果不一致的情况,也就是前一次的结果把后一次覆盖了。

解决方法

  1. loading遮罩

    直接将用户交互的部分挡住,或者将切换状态的button禁用也是一样的效果。为了保证用户体验可能需要做一些超时处理和新的UI。

  2. 取消请求

    个人感觉的最优解?axios、fetch和Promise都可以取消。

  3. 不处理无用请求

    也就是记录上一次点击的tag,不保存其他tag的数据,不过请求还是会正常发送,略微有些浪费资源,类似于两次握手和三次握手的关系?