对于chrome来说,同域名下资源加载的最大并发连接数为6(源码中写死),当资源文件大于6时,多于6个的文件就会进入待定,等第一批加载完才会加载第二批的6个图片资源,这样就增加了等待时间。http/1有并发限制,http/2没有。
那么为什么chrome会做出如此的限制呢?
- 对操作系统端口资源考虑。PC总端口数为65536,那么一个tcp连接(http也是tcp)就需要占用一个端口。过多的请求就会占用过多端口资源。
- 过多并发导致频繁切换产生性能问题。一个线程对应一个http请求,如果并发数量过大会导致线程频繁切换。而线程的上下文切换有时并不是轻量级的资源(对比进程切换是轻量级)。所以,请求控制器中国产生了一个连接池,同域名下连接池为6。
- 客户端良知机制。为了防止两个应用抢占资源时导致强势一方无限制的获取资源,而弱势一方永远处于等待状态。
常见优化手段:
- 小图片合并成大图(雪碧图)。减少图片资源的请求数量。
- 图片懒加载。
- 直接使用http/2避免限制。
- 域名散发。将请求通过多个域名分开请求。但建议4个左右,避免过多域名造成dns解析性能问题。
域名散发实现思路:
- 在DNS服务商中申请多个域名,指向同一个IP服务。
- 对后台返回的数据进行域名处理,对图片链接,进行域名替换。
- 域名替换完成,通过localStorage进行key/value保存。以使得相同图片在下一次展示时,能使用浏览器缓存,而非重复加载。key保存图片资源路径名,value保存图片完整链接。
// 替换域名
function replaceDomain(data) {
let imgUrlObj = localStorage.getItem('imgUrlObj') || {} // 获取本地保存的图片链接,能正常使用缓存
if (typeof(imgUrlObj) === 'string') { // 判断是否为JSON对象,不是则转换
imgUrlObj = JSON.parse(imgUrlObj)
}
let index = Math.floor(Math.random() * 4.99) // 随机0-4的下标
try {
data = JSON.stringify(data)
data = data.replace(/www\.baidu\.com\/image(.*?)(jpg|png|jpeg)/g, (...params) => { // 查找图片的url并对其进行操作
let sourceUrl = params[1] + params[2] // 图片资源名称,未包含域名。如:整条图片链接为:www.baidu.com/image/123.png; 现保存为:/image/123.png
if (!imgUrlObj[sourceUrl]) { // 未保存在本地,则新产生域名
let imgUrl = `node${[1, 2, 3, 4, 5][index % 5]}.baidu.com/image/${sourceUrl}` // 域名替换,如:从 www.baidu.com 替换到 node1.baidu.com,node2.baidu.com
imgUrlObj[sourceUrl] = imgUrl // 同时保存好新的域名,在这就体现了使用JSON对象的好处,图片资源路径名当key值,图片完整链接当value值
localStorage.setItem('imgUrlObj', JSON.stringify(imgUrlObj))
index++
return imgUrl
} else { // 保存到了本地,则直接使用localStorage的url
return imgUrlObj[sourceUrl]
}
})
data = JSON.parse(data)
} catch (e) {
console.log('replaceDomain error')
console.log(e)
}
return data
}