超大规模数据传输速度优化

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
上一篇下一篇

猜你喜欢

热点阅读