性能优化

135 阅读4分钟

http

http 与 TCP

  • http - 应用层 < = > TCP - 传输层
  • 关联 http 基于 TCP实现连接 => http请求、发送、断开

UDP vs TCP

  • UDP:保障速度面向链接的
  • TCP:保障稳定性,面向确认的,更准确

keep-alive

  • 保持TCP的连续畅通 - 不用反复地建立连接

1.0和2.0的区别:

2.0多条并发请求复用同一条通路 - 复用通路,无并发限制

http - 无状态 < = > TCP - 有状态

优化点: socket 连接(封装化的TCP)。让我们的应用,更加方便地使用调用。

http和https

  • https: HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

  • 原理: 20220415173708.jpg

  • HTTPS多次连接:导致网络请求加载时间延长;增加开销和功耗

    优化:对于https的优化,我们建议合并请求 长链接

  • SSL: TLS(Transport Layer Security) 是 SSL(Secure Socket Layer) 的后续版本,它们是用于在互联网两台计算机之间用于身份验证加密的一种协议。

域名解析

  1. 浏览器缓存中 - 浏览器中会缓存DNS一段时间

  2. 系统缓存 - 系统中找缓存 -> HOST

  3. 路由器缓存 - 各级路由器缓存域名信息

  4. 运营商地方站点的缓存信息 - partner

  5. 根域名服务器

    优化: CDN - Content Delivery Network
    1. 为同一个主机配置多个IP地址
    2. LB - 负载均衡
    // => 缓存 => 各级缓存 => 浏览器区分缓存

web服务器

常见的web服务器 apache ngnix

  1. 接收请求 => 传递给服务端代码
  2. 通过反向代理 => 传递给其他服务器
  3. 不同域名 => 指向相同ip的服务器 => ngnix域名解析 => 引导到不同的服务监听端口

服务 涉及到 网络优化

  • 手写并发 - QPS
    // 面试:并发优化 10个请求,由于后台或者业务需求只能同时执行三个
    // 分析:
    // 输入:promise数组、limit参数
    // 存储:reqpool - 并发池
    // 思路:塞入 + 执行
    function qpsLimit(requestPipe, limitMax = 3) {
        let reqPool = []
        let reqMap = new Map()

        // 往并发池里塞入promise
        const add = () => {
            let _req = requestPipe.shift()
            reqPool.push(_req)
        }
    
        // 执行实际请求
        const run = () => {
            if(requestPipe.length === 0) return
            // 池子满了发车后,直接race
            let _finish = Promise.race(reqPool)

            _finish.then(res => {
                // 做一个id整理
                let _done = reqPool.indexOf(_finish)
                reqPool.splice(_done, 1)
                add()
            })
            run()
        }

        while(reqPool.length < limitMax) {
            add()
        }
        run()
    }

浏览器渲染时

  • 浏览器执行顺序 主线:HTML => DOM + CSSOM => renderTree + js => layout => paint 支线: repaint - 改变文本、颜色等 展示 reflow - 元素几何尺寸变了

=> 优化点:减少repaint(重绘),避免reflow(回流)
=> display: none => reflow; visibility:hidden; => repaint

image.png

脚本执行时 - JS

mark & sweep => 触达标记,锁定清空、未触达直接抹掉

    // 内存分配:申明变量、函数、对象
    // 内存使用:读写内存
    // 内存释放

    const zhaowa = {
        js: {
            performance: 'good',
            teacher: '云隐'
        }
    }

    // 建立引用关系
    const _obj = zhaowa

    // 引用源给替换掉了 - 暂未gc(垃圾回收)
    zhaowa = 'best'

    // 深入层级做引用 - 暂未gc
    const _class = _obj.js

    // gc 完成
    _class = null
    
    // => 1. 对象层级,宜平不宜深 2. 深层引用最好深拷贝,或者用完直接销毁 3. 避免循环引用
    function traverseTree(node1, node2) { // node1和node2循环引用了永远无法gc
        node1.parent = node2;
        node2.children = node1; 
    }

    // 内存泄露
    // 莫名其妙的全局变量
    function foo() {
        bar1 = ''
        this.bar2 = ''
    }

    // 未清理的定时器
    setInterval(() => {
    }, 1000)

    // 使用后的闭包
    function zhaowa() {
        const _no = 1
        return {
            number: _no
        }
    }

打包配置优化

    // 1. 懒加载 - 非必要不加载
    // 2. 按需引入 - 非必要不引入
    // 3. 抽离公共 - 相同项目合并公用

面试题:

览器与服务器建立一个TCP连接后,是否会在完成一个http请求后断开?什么条件下会断开?

HTTP/1.0中,一个http请求收到服务器响应后,会断开对应的TCP连接。这样每次请求,都需要重新建立TCP连接,这样一直重复建立和断开的过程,比较耗时。所以为了充分利用TCP连接,可以设置头字段Connection: keep-alive,这样http请求完成后,就不会断开当前的TCP连接,后续的http请求可以使用当前TCP连接进行通信。HTTP/1.1Connection写入了标准,默认值为keep-alive。除非强制设置为Connection: close,才会在请求后断开TCP连接。默认情况下建立的TCP连接不会断开,只有在请求头中设置Connection: close才会在请求后关闭TCP连接。

一个TCP连接可以同时发送几个HTTP请求? HTTP/1.1中,单个TCP连接,在同一时间只能处理一个http请求,HTTP2提供了多路传输功能,多个http请求,可以同时在同一个TCP连接中进行传输。

浏览器http请求的并发性是如何体现的?并发请求的数量有没有限制? 面资源请求时,浏览器会同时和服务器建立多个TCP连接,在同一个TCP连接上顺序处理多个HTTP请求。所以浏览器的并发性就体现在可以建立多个TCP连接,来支持多个http同时请求。

Chrome浏览器最多允许对同一个域名Host建立6个TCP连接,不同的浏览器有所区别。