1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Websocket 可以玩出些什么花兒?

        共 4089字,需瀏覽 9分鐘

         ·

        2022-02-14 23:24

        術(shù)??堅(jiān)??

        一、首先我們要了解 Websocket 握手的原理

        請(qǐng)求頭特征

        • HTTP 必須是 1.1 GET 請(qǐng)求
        • HTTP Header 中 Connection 字段的值必須為 Upgrade
        • HTTP Header 中 Upgrade 字段必須為 websocket
        • Sec-WebSocket-Key 字段的值是采用 base64 編碼的隨機(jī) 16 字節(jié)字符串
        • Sec-WebSocket-Protocol 字段的值記錄使用的子協(xié)議,比如 binary base64
        • Origin 表示請(qǐng)求來(lái)源

        響應(yīng)頭特征

        • 狀態(tài)碼是 101 表示 Switching Protocols
        • Upgrade / Connection / Sec-WebSocket-Protocol 和請(qǐng)求頭一致
        • Sec-WebSocket-Accept 是通過(guò)請(qǐng)求頭的 Sec-WebSocket-Key 生成

        二、短連接輪詢、長(zhǎng)連接、Websocket 橫向?qū)Ρ?/span>

        1. 短連接輪詢

        • 很耗費(fèi) TCP 連接
        • 而且 Header 重復(fù)發(fā)送
        • 且通過(guò)宏任務(wù)發(fā)起,受限于 Event Loop,無(wú)法保證及時(shí)性
        • 同時(shí)無(wú)效請(qǐng)求會(huì)很多

        2. 長(zhǎng)連接

        • HTTP keep-alive 開(kāi)啟后雖然 TCP 可以復(fù)用,但是 Header 重復(fù)的問(wèn)題并沒(méi)有解決
        • 同時(shí) HTTP keep-alive 還有一個(gè)有效期,有效期結(jié)束后服務(wù)端會(huì)發(fā)偵查幀探查 TCP 是否有效

        題外話:

        HTTP keep-alive 的作用是,告知服務(wù)端持久化當(dāng)前的?TCP?連接,不要立即斷開(kāi),以便后續(xù)的 HTTP 請(qǐng)求復(fù)用它,也就是我們所說(shuō)的「長(zhǎng)連接」

        HTTP 的 keep-alive 是為了讓 TCP 活久一點(diǎn),而 TCP 本身也有一個(gè) keepalive(注意沒(méi)有橫杠哦)機(jī)制。這是 TCP 的一種檢測(cè)連接狀況的?;顧C(jī)制,keepalive 是 TCP ?;疃〞r(shí)器:TCP 建立后,如果閑置沒(méi)用,服務(wù)器不可能白等下去,閑置一段時(shí)間[可設(shè)置]后,服務(wù)器就會(huì)嘗試向客戶端發(fā)送偵測(cè)包,來(lái)判斷 TCP 連接狀況,如果沒(méi)有收到對(duì)方的回答(ACK包),就會(huì)過(guò)一會(huì)[可設(shè)置]再偵測(cè)一次,如果多次[可設(shè)置]都沒(méi)回答,就會(huì)丟棄這個(gè) TCP 連接

        (TCP keepalive ?;钍疽鈭D)

        3. Websocket

        • 和 HTTP 一樣都是建立在 TCP 協(xié)議之上,但只需一次 HTTP 握手,就能建立持久性連接,后續(xù)就不走 HTTP 了,而是 WebSocket 特有的數(shù)據(jù)幀
        • 全雙工通信,雙向數(shù)據(jù)傳輸
        • 數(shù)據(jù)格式輕量,且支持發(fā)送二進(jìn)制數(shù)據(jù),支持 ws 和加密的 wss

        三、我在微信小程序中利用 WebSocket 都搗鼓了什么?

        1 驗(yàn)簽鑒權(quán)及對(duì)應(yīng)的容錯(cuò)策略(登錄態(tài)要求、峰值訪問(wèn)、服務(wù)端宕機(jī)異常)

        背景與目的:

        • websocket 握手后,接口請(qǐng)求即可以放棄 HTTP 改走 weboskcet,但大部分業(yè)務(wù)接口都要求登錄態(tài),因此握手成功后必須先走一次簽名鑒權(quán),獲取登錄態(tài)
        • 當(dāng)出現(xiàn)大流量訪問(wèn)的場(chǎng)景(如大促、熱點(diǎn)活動(dòng)等)或服務(wù)端出 bug 而導(dǎo)致服務(wù)端宕機(jī),前端會(huì)做 對(duì)應(yīng)容錯(cuò),將位于內(nèi)存的等待隊(duì)列中的待發(fā)送請(qǐng)求立即降級(jí)成 HTTP 發(fā)送出去

        偽碼示意:

        SocketTask.onOpen(function?()?{
        ??SocketTask.sendSocketMessage({
        ?????msg_type:?'驗(yàn)簽',
        ?????token:?'xxx'
        ??},?(response)?=>?{
        ??????console.log(response.user_id,?response.access_token)

        ??????//?通道可用,打個(gè)標(biāo)記
        ??????global.isSocketAvaliable?=?true;
        ??})
        })

        2 心跳?;睿p少 TCP 占用)

        背景與目的:為了減少 TCP 連接的無(wú)效占用,客戶端定時(shí)發(fā)送一個(gè)空包到服務(wù)端,告知服務(wù)端不要銷(xiāo)毀這條 socket,如果服務(wù)端超過(guò)一定時(shí)間都沒(méi)收到心跳包,則將關(guān)閉并銷(xiāo)毀該 socket

        偽碼示意:

        SocketTask.onOpen(function?()?{
        ??SocketTask.sendSocketMessage({
        ?????msg_type:?'驗(yàn)簽'
        ?????token:?'xxx'
        ??},?(response)?=>?{
        ??????console.log(response.user_id,?response.access_token)

        ??????//?通道可用,打個(gè)標(biāo)記
        ??????global.isSocketAvaliable?=?true;
        ??????
        ??????//?驗(yàn)簽成功,開(kāi)始定時(shí)發(fā)送心跳包
        ??????setInterval(()?=>?{
        ??????????SocketTask.sendSocketMessage({
        ????????????msg_type:?'心跳'
        ??????????});
        ??????});
        ???});
        })

        3 模擬 RTT(用于弱網(wǎng)體驗(yàn)優(yōu)化)

        背景與目的:在發(fā)送心跳包時(shí),可得知一個(gè)心跳包的 RTT,以此模擬當(dāng)前用戶網(wǎng)絡(luò)環(huán)境的 TCP RTT,并據(jù)此計(jì)算出平滑 RTO,用于弱網(wǎng)體驗(yàn)優(yōu)化

        偽碼示意:

        SocketTask.onOpen(function?()?{
        ??SocketTask.sendSocketMessage({
        ?????msg_type:?'驗(yàn)簽'
        ?????token:?'xxx'
        ??},?(response)?=>?{
        ??????console.log(response.user_id,?response.access_token)

        ??????//?通道可用,打個(gè)標(biāo)記
        ??????global.isSocketAvaliable?=?true;
        ??????
        ??????//?驗(yàn)簽成功,開(kāi)始定時(shí)發(fā)送心跳包
        ??????setInterval(()?=>?{
        ??????????//?計(jì)算?RTT
        ??????????const?begin?=?Date.now();

        ??????????SocketTask.sendSocketMessage({
        ????????????msg_type:?'心跳'
        ??????????},?()?=>?{
        ????????????const?end?=?Date.now();
        ????????????
        ????????????const?RTT?=?begin?-?end;
        ????????????
        ????????????const?smoothedRTO?=?cal(RTT);
        ????????????
        ????????????global.smoothedRTO?=?smoothedRTO;
        ??????????});
        ??????});
        ???});
        });

        4 Snappy 壓縮(橫向?qū)Ρ攘?gzip / zip / 7z)

        背景與目的:在小程序中引入第三方壓縮包(犧牲小程序包體積),減少 websocket 傳輸?shù)淖止?jié)數(shù)

        偽碼示意:

        ??import?Snappy?from?'snappy';

        ??SocketTask.sendSocketMessage?=?function?(msg)?{
        ?????const?encryptedMsg?=?Snappy.encode(msg);
        ?????
        ?????wx.send(encryptedMsg);
        ??}

        5 重連(階梯式錯(cuò)位重連,避免擁擠)

        背景與目的:用戶的網(wǎng)絡(luò)環(huán)境不穩(wěn)定,可能會(huì)存在主動(dòng) / 被動(dòng)斷開(kāi) socket 的情況,需要進(jìn)行自動(dòng)重連

        偽碼示意:

        SocketTask.onClose(function?()?{
        ??//?限定最大重連次數(shù)
        ??if?(retryCount?>?maxCount)?{
        ????return;
        ??}
        ??
        ??retryCount++;

        ??setTimeout(()?=>?{
        ????SocketTask.connectSocket();
        ??},?retryCount?*?1000?+?Math.random()?*?1000);
        });

        6 埋點(diǎn)中間層緩存(重復(fù)的用戶信息可以不用每次都上報(bào),支持刷新緩存)

        背景與目的:為減少網(wǎng)絡(luò)傳輸?shù)陌w積,通過(guò) websocket 上報(bào)埋點(diǎn)日志時(shí),可以把部分重復(fù)字段值在第一次上報(bào)時(shí)緩存在服務(wù)端,從第二次上報(bào)開(kāi)始只上報(bào)值不重復(fù)的字段,然后由服務(wù)端做日志合并

        偽碼示意:

        SocketTask.sendSocketMessage({
        ?????msg_type:?'埋點(diǎn)日志',
        ?????logs:?{
        ???????country:?'China',?//?可緩存字段
        ???????city:?'北京',?//?可緩存字段
        ???????platform:?'安卓',?//?可緩存字段
        ???????click_some_btn:?true?//?動(dòng)態(tài)變化的埋點(diǎn)字段
        ?????},
        ?????cacheFields:?['country',?'city',?'platform']?//?只在第一次上報(bào)時(shí)攜帶
        ?});

        7 啟用 TCP_NODELAY

        TCP_NODELAY 是用來(lái)禁用 Nagle 算法的。Nagle 算法設(shè)計(jì)的目的是提高網(wǎng)絡(luò)帶寬利用率,其核心思路是「合并小的 TCP 包為一個(gè)大的 TCP 包」,避免過(guò)多的小包的 TCP 頭部浪費(fèi)網(wǎng)絡(luò)帶寬

        參考資料:https://www.zhihu.com/question/42308970

        H5-Dooring, 讓H5制作, 更簡(jiǎn)單

        ???

        便內(nèi),對(duì)^_^

        ?、點(diǎn)?~

        瀏覽 33
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            中国无码电影 | 无遮挡裸光屁屁打屁股绿帽社 | 男男撅起屁股挨cao视频 | 美女被男人操的视频 | 大乳女神bigboobs4k | 欧美性爱一级视频 | 精品国产欧美一区二区三区成人 | t66y地址1地址2满18 | 天堂草原电视剧图片在线 | 大香伊人久久 |