超大规模数据传输速度优化
2021-06-22 本文已影响0人
小俊的世界
起因
最近项目中,有一个统计接口,返回数据大小1.3M,耗时38.89s,而内容下载达到34.57s,这是没有办法接受的。
image.png image.png
分析
并发策略
利用并发的策略,将原有的接口改成分页查询的接口后
处理的步骤:
1.先查询出总数
2.根据要分多少次查询,设置并发请求
3.进行并发请求
class ConcurrentRequests {
async paging(api, params) { // 通过控制并发数处理
console.time(`${api.name} time`)
const back = await api({ ...params, pageSize: 1, currPage: 1 }) // 首次查询到总数
if (!back.success) throw new Error('接口调用不成功!')
if (!back.result) throw new Error('没有返回正确的数据结构!')
if (!params.num) params.num = 4 // 默认为4
const total = back.result.total
const totalPage = params.num
const pageSize = Math.ceil(total / params.num)
const requests = []
for (let index = 0; index <= totalPage; index++) {
requests.push(api({ ...params, num: null, pageSize, currPage: index}))
}
const arr = await Promise.all(requests)
let list = []
arr.forEach(item => {
list = list.concat(item.result.list)
})
console.timeEnd(`${api.name} time`)
return list
}
}
export const concurrentRequests = new ConcurrentRequests()
export const pagingConcurrentRequests = concurrentRequests.paging
最终的效果还是相当明显的,13s左右。
image.png
多域名并发
在浏览器的同源策略下,请求并发是有限制的,chrome下的并发数的限制是6个,也就是我一次性超过6个请求的话,其实是不划算的,因为相当于有些请求是需要排队的,那么总时长将会加大。
基本的思路
1.为并发请求打上标志,标识为并发请求
2.拦截并发请求(使用到第三方库ajax-hook),并替换域名后继续请求
class ConcurrentRequests {
async paging(api, params) { // 通过控制并发数处理
console.time(`${api.name} time`)
const back = await api({ ...params, pageSize: 1, currPage: 1 }) // 首次查询到总数
if (!back.success) throw new Error('接口调用不成功!')
if (!back.result) throw new Error('没有返回正确的数据结构!')
if (!params.num) params.num = 4 // 默认为4
const total = back.result.total
const totalPage = params.num
const pageSize = Math.ceil(total / params.num)
const requests = []
for (let index = 0; index <= totalPage; index++) {
// isConcurrentRequest 标识是否并发 用于开启多域名
requests.push(api({ ...params, num: null, pageSize, currPage: index, isConcurrentRequest: true }))
}
const arr = await Promise.all(requests)
let list = []
arr.forEach(item => {
list = list.concat(item.result.list)
})
console.timeEnd(`${api.name} time`)
return list
}
}
export const concurrentRequests = new ConcurrentRequests()
export const pagingConcurrentRequests = concurrentRequests.paging
拦截处理:
import { proxy } from 'ajax-hook'
import Vue from 'vue'
// 请求并发处理
function dealConcurrentRequest(config) {
if (config.url && (config.url.indexOf('/promis-web/') !== -1)) {
if (!config.body) return
const body = JSON.parse(config.body)
if (!body.isConcurrentRequest) return
const concurrentDomain = Vue.prototype.$concurrentDomain ? eval(`(${Vue.prototype.$concurrentDomain})`) : []
const trail = config.url.split('/promis-web/')[1]
const baseUrl = concurrentDomain[counter++ % concurrentDomain.length]
config.url = baseUrl + 'promis-web/' + trail
}
}
proxy({
onRequest: (config, handler) => {
// 请求并发处理
dealConcurrentRequest(config)
handler.next(config)
},
onError: (err, handler) => {
handler.next(err)
},
onResponse: (response, handler) => {
handler.next(response)
}
})
我们的备用并发域名设有6个:
image.png
设置了并发请求数 20,得出的结果为 5s
image.png