<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Websocket 可以玩出些什么花兒?

          共 4089字,需瀏覽 9分鐘

           ·

          2022-02-14 23:24

          ????

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

          請求頭特征

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

          響應頭特征

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

          二、短連接輪詢、長連接、Websocket 橫向對比

          1. 短連接輪詢

          • 很耗費 TCP 連接
          • 而且 Header 重復發(fā)送
          • 且通過宏任務發(fā)起,受限于 Event Loop,無法保證及時性
          • 同時無效請求會很多

          2. 長連接

          • HTTP keep-alive 開啟后雖然 TCP 可以復用,但是 Header 重復的問題并沒有解決
          • 同時 HTTP keep-alive 還有一個有效期,有效期結束后服務端會發(fā)偵查幀探查 TCP 是否有效

          題外話:

          HTTP keep-alive 的作用是,告知服務端持久化當前的?TCP?連接,不要立即斷開,以便后續(xù)的 HTTP 請求復用它,也就是我們所說的「長連接」

          HTTP 的 keep-alive 是為了讓 TCP 活久一點,而 TCP 本身也有一個 keepalive(注意沒有橫杠哦)機制。這是 TCP 的一種檢測連接狀況的保活機制,keepalive 是 TCP 保活定時器:TCP 建立后,如果閑置沒用,服務器不可能白等下去,閑置一段時間[可設置]后,服務器就會嘗試向客戶端發(fā)送偵測包,來判斷 TCP 連接狀況,如果沒有收到對方的回答(ACK包),就會過一會[可設置]再偵測一次,如果多次[可設置]都沒回答,就會丟棄這個 TCP 連接

          (TCP keepalive 保活示意圖)

          3. Websocket

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

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

          1 驗簽鑒權及對應的容錯策略(登錄態(tài)要求、峰值訪問、服務端宕機異常)

          背景與目的:

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

          偽碼示意:

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

          ??????//?通道可用,打個標記
          ??????global.isSocketAvaliable?=?true;
          ??})
          })

          2 心跳保活(減少 TCP 占用)

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

          偽碼示意:

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

          ??????//?通道可用,打個標記
          ??????global.isSocketAvaliable?=?true;
          ??????
          ??????//?驗簽成功,開始定時發(fā)送心跳包
          ??????setInterval(()?=>?{
          ??????????SocketTask.sendSocketMessage({
          ????????????msg_type:?'心跳'
          ??????????});
          ??????});
          ???});
          })

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

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

          偽碼示意:

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

          ??????//?通道可用,打個標記
          ??????global.isSocketAvaliable?=?true;
          ??????
          ??????//?驗簽成功,開始定時發(fā)送心跳包
          ??????setInterval(()?=>?{
          ??????????//?計算?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 壓縮(橫向對比了 gzip / zip / 7z)

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

          偽碼示意:

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

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

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

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

          偽碼示意:

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

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

          6 埋點中間層緩存(重復的用戶信息可以不用每次都上報,支持刷新緩存)

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

          偽碼示意:

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

          7 啟用 TCP_NODELAY

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

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

          H5-Dooring, 讓H5制作, 更簡單

          ???

          便^_^

          ??~

          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  69免费视频 | 蜜桃传媒一区二区 | 久久国产福利视频 | 成人娱乐中文字幕 | 黄色操逼大片 |