亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線(xiàn)實(shí)戰(zhàn)洞察。

基于WebSocket的多端實(shí)時(shí)通信實(shí)戰(zhàn):連接管理、心跳與消息路由

基于WebSocket的多端實(shí)時(shí)通信實(shí)戰(zhàn):連接管理、心跳與消息路由 簡(jiǎn)介基于WebSocket的LAS多端互通畢業(yè)設(shè)計(jì)項(xiàng)目面向需要實(shí)現(xiàn)實(shí)時(shí)位置感知與多端數(shù)據(jù)同步的開(kāi)發(fā)者重點(diǎn)解決傳統(tǒng)HTTP只能請(qǐng)求/響應(yīng)、無(wú)法主動(dòng)推送導(dǎo)致的位置信息滯后問(wèn)題。壓縮包共55個(gè)文件包含46個(gè)Python源碼文件、7張JPG效果圖、1個(gè)Markdown說(shuō)明文檔及License文件整體僅485KB輕量而完整。項(xiàng)目采用服務(wù)端集中轉(zhuǎn)發(fā)與客戶(hù)端異步接入的方式并配有插件化模塊設(shè)計(jì)覆蓋聊天橋接、在線(xiàn)玩家查詢(xún)、簽到、坐標(biāo)共享等典型場(chǎng)景源碼對(duì)服務(wù)端、客戶(hù)端、插件邏輯做了清晰劃分JPG預(yù)覽圖可直觀對(duì)照運(yùn)行效果便于快速理解WebSocket雙向通信在LAS系統(tǒng)中的應(yīng)用機(jī)制。目前已有38人學(xué)習(xí)參考適合作為畢業(yè)設(shè)計(jì)參考或課程項(xiàng)目拓展也可在讀懂核心流程后自行擴(kuò)展消息類(lèi)型與前端交互界面尤其能體現(xiàn)對(duì)通信協(xié)議與工程結(jié)構(gòu)的綜合運(yùn)用。1. 基于WebSocket的LAS多端互通先說(shuō)清楚這東西解決什么中午改完桌面端的排班模板手機(jī)上的小程序要能立刻看到新?tīng)顟B(tài)而不是等用戶(hù)手動(dòng)刷新或者輪詢(xún)兜底。這就是LAS多端互通最典型的場(chǎng)景一套業(yè)務(wù)服務(wù)同時(shí)掛了桌面端、手機(jī)端、網(wǎng)頁(yè)端任何一端產(chǎn)生變化其它端要在秒級(jí)內(nèi)感知到。傳統(tǒng)HTTP做不到實(shí)時(shí)下行推送WebSocket長(zhǎng)連接才是承擔(dān)這個(gè)角色的主干。標(biāo)題里的LAS在這里不是某個(gè)公開(kāi)標(biāo)準(zhǔn)它就是一個(gè)業(yè)務(wù)代號(hào)你可以把它映射成你手頭任何一套需要多端協(xié)作的系統(tǒng)名。「基于WebSocket的LAS多端互通.zip」拆開(kāi)看就三件事用WebSocket建立長(zhǎng)連接在連接之上做LAS業(yè)務(wù)消息的轉(zhuǎn)發(fā)再解決多端同時(shí)在線(xiàn)的身份識(shí)別與消息路由。比做一個(gè)單聊或通知推送復(fù)雜的地方在于同一個(gè)用戶(hù)可能同時(shí)在電腦瀏覽器、手機(jī)App、微信小程序里掛著服務(wù)端得知道一條消息該發(fā)給哪幾個(gè)連接哪些連接其實(shí)已經(jīng)死了以及消息發(fā)過(guò)去之后對(duì)方到底收沒(méi)收到。這篇筆記適合兩類(lèi)人。一類(lèi)是后端要接WebSocket但之前只寫(xiě)過(guò)接口的能跟著把連接管理、心跳機(jī)制和消息路由跑起來(lái)另一類(lèi)是前端要把網(wǎng)頁(yè)、小程序、桌面端接到同一套實(shí)時(shí)鏈路上的看完能知道服務(wù)端是怎么判定自己掉線(xiàn)的以及前端該怎么配合。下面所有代碼我都按Node.js的ws庫(kù)來(lái)寫(xiě)這套方案換到Netty、Spring WebSocket或者Go的gorilla/websocket上思路是同一套。2. 連接管理是互通的底座把每個(gè)端變成可尋址的對(duì)象多端互通的第一步不是寫(xiě)消息轉(zhuǎn)發(fā)而是先讓服務(wù)端能認(rèn)得出每一個(gè)連接。裸的WebSocket連接在服務(wù)端只是一個(gè)socket對(duì)象它不知道自己屬于哪個(gè)用戶(hù)、哪個(gè)端、在哪個(gè)房間。如果直接拿這個(gè)socket做消息收發(fā)你會(huì)很快發(fā)現(xiàn)代碼變成一團(tuán)亂麻要廣播的時(shí)候不知道發(fā)給誰(shuí)用戶(hù)換設(shè)備登錄后舊連接也沒(méi)法處理。所以第一層要做的是給連接套上身份。2.1 為什么不能直接用裸連接來(lái)收發(fā)消息很多第一次接觸WebSocket的人會(huì)直接這樣寫(xiě)connection事件里拿到socket然后往socket上綁onmessage收到什么轉(zhuǎn)發(fā)什么。單連接demo沒(méi)問(wèn)題一旦出現(xiàn)「用戶(hù)A在手機(jī)上發(fā)一條消息他桌面端和網(wǎng)頁(yè)端也要同時(shí)收到」光有socket就不夠了因?yàn)榉?wù)端根本沒(méi)有「用戶(hù)」這個(gè)概念只有一堆不知道是誰(shuí)的連接。LAS多端互通里最常見(jiàn)的狀態(tài)是一個(gè)用戶(hù)同時(shí)掛了三個(gè)連接三個(gè)連接的契約還可能不一樣——網(wǎng)頁(yè)端只關(guān)心排班變更桌面端還會(huì)同步模板文件手機(jī)端要收審批通知。你不能把這三類(lèi)消息無(wú)差別群發(fā)給所有連接。所以必須在連接之上加一層會(huì)話(huà)Session抽象把「物理連接」和「邏輯身份」分開(kāi)。連接斷開(kāi)只會(huì)影響某個(gè)connId而用戶(hù)的多個(gè)連接之間是弱關(guān)聯(lián)其中一個(gè)掉了不應(yīng)該影響另外兩個(gè)繼續(xù)收消息。我一般會(huì)把連接生命周期里的注冊(cè)、心跳、鑒權(quán)、路由全部收口到一個(gè)ConnectionManager里業(yè)務(wù)層不直接碰ws對(duì)象。這樣做還有個(gè)好處將來(lái)把單機(jī)改成多實(shí)例部署時(shí)ConnectionManager內(nèi)部換成Redis維護(hù)連接索引業(yè)務(wù)代碼不用動(dòng)。2.2 連接注冊(cè)clientId 與 connectionId 的雙層索引先定協(xié)議客戶(hù)端握手時(shí)在URL的query里帶clientId這個(gè)ID代表一個(gè)業(yè)務(wù)用戶(hù)由LAS自己的登錄態(tài)生成服務(wù)端每接受一條連接就生成一個(gè)全局唯一的connectionId。中間層維護(hù)三張表connMapconnectionId - WebSocket 實(shí)例用于直接發(fā)消息userMapclientId - Set 用于按用戶(hù)找到他所有的端roomMaproomId - Set 用于按房間做廣播。下面是最小可運(yùn)行的注冊(cè)邏輯// server.js —— WebSocket 連接注冊(cè)與用戶(hù)索引維護(hù) const { WebSocketServer } require(ws); const crypto require(crypto); const connMap new Map(); // connectionId - ws const userMap new Map(); // clientId - SetconnectionId // 用 wss 實(shí)例監(jiān)聽(tīng)端口按 LAS 網(wǎng)關(guān)配置調(diào)整比如 8080 const wss new WebSocketServer({ port: 8080, maxPayload: 64 * 1024 * 1024 // 允許 64MB 單幀給文件類(lèi)消息留余量 }); function parseClientId(url) { // 握手地址形如: /?clientIdU10086tokenxxx // 生產(chǎn)環(huán)境這里的 token 要做簽名校驗(yàn)不能用純明文 return new URLSearchParams(url.split(?)[1]).get(clientId); } wss.on(connection, (ws, req) { const connId crypto.randomUUID(); const clientId parseClientId(req.url); if (!clientId) { ws.close(4001, missing clientId); // 握手失敗直接斷開(kāi) return; } connMap.set(connId, ws); if (!userMap.has(clientId)) userMap.set(clientId, new Set()); userMap.get(clientId).add(connId); // 把 connId 掛到 ws 上后面 onmessage 里好取 ws.connId connId; ws.clientId clientId; ws.on(close, () { connMap.delete(connId); const conns userMap.get(clientId); if (conns) { conns.delete(connId); if (conns.size 0) userMap.delete(clientId); } }); });注冊(cè)這段邏輯里parseClientId 從握手URL解析業(yè)務(wù)用戶(hù)ID這個(gè)設(shè)計(jì)是故意的WebSocket 的握手就是一次普通HTTP請(qǐng)求可以把鑒權(quán)信息放進(jìn)query或header不要在建立連接之后再單獨(dú)發(fā)一條「登錄消息」——那樣會(huì)給中間層留下一個(gè)沒(méi)身份的空窗期。ws.close(4001, missing clientId) 是拒絕握手的標(biāo)準(zhǔn)姿勢(shì)客戶(hù)端會(huì)收到4001錯(cuò)誤碼并觸發(fā)onclose便于前端區(qū)分「被拒」和「網(wǎng)絡(luò)斷開(kāi)」。注意maxPayload這個(gè)參數(shù)。LAS如果涉及模板文件、簡(jiǎn)報(bào)圖片甚至點(diǎn)云預(yù)覽單幀消息很容易超過(guò)默認(rèn)1MB上限。我按64MB開(kāi)是給大數(shù)據(jù)量消息留余地但代價(jià)是內(nèi)存壓力增加業(yè)務(wù)不需要傳大文件時(shí)建議調(diào)回1MB~8MB。2.3 房間分組把廣播范圍圈出來(lái)多端互通不可能所有消息都發(fā)給所有人。LAS里典型的房間模型是「項(xiàng)目組」一個(gè)項(xiàng)目組的變更消息只需要推給這個(gè)組里的人跨組消息屬于越權(quán)。所以第三張表roomMap做的事就是把連接歸組。// room.js —— 房間管理基于 Set 做連接維度分組 const roomMap new Map(); // roomId - SetconnectionId function joinRoom(connId, roomId) { if (!roomMap.has(roomId)) roomMap.set(roomId, new Set()); roomMap.get(roomId).add(connId); } function leaveRoom(connId, roomId) { roomMap.get(roomId)?.delete(connId); } function broadcastToRoom(roomId, message) { const conns roomMap.get(roomId); if (!conns) return; const raw JSON.stringify(message); for (const connId of conns) { const ws connMap.get(connId); // readyState 1 表示連接處于 OPEN 狀態(tài)防止往 CLOSED 連接上寫(xiě) if (ws ws.readyState 1) ws.send(raw); } }這里有一個(gè)需要想清楚的點(diǎn)房間維度到底按clientId還是connectionId。我上面是按connectionId存的好處是一個(gè)用戶(hù)多個(gè)端在不同房間時(shí)互不干擾代價(jià)是用戶(hù)換房間要做兩次leaveRoomjoinRoom。如果你確定一個(gè)用戶(hù)所有端永遠(yuǎn)在同一個(gè)房間就按clientId存房間每次廣播時(shí)先展開(kāi)成connectionId列表再發(fā)送省掉一部分重復(fù)消息。兩個(gè)方案都能跑選擇標(biāo)準(zhǔn)只有一個(gè)你的業(yè)務(wù)允不允許同一個(gè)人的兩個(gè)端處在不同項(xiàng)目組。3. WebSocket心跳機(jī)制實(shí)現(xiàn)服務(wù)端如何判斷「對(duì)方還活著」連接建立不等于連接健康。LAS多端互通里最常見(jiàn)的翻車(chē)現(xiàn)場(chǎng)是客戶(hù)端突然從4G切到Wi-FiTCP連接已經(jīng)死了但服務(wù)端和客戶(hù)端都沒(méi)有立刻感知服務(wù)端還往這個(gè)死連接上發(fā)消息客戶(hù)端一直收不到也不重連。要解決這個(gè)問(wèn)題必須有一套心跳機(jī)制。這也是WebSocket長(zhǎng)連接工程里最值得摳細(xì)節(jié)的部分。3.1 心跳機(jī)制實(shí)現(xiàn)為什么是服務(wù)端主動(dòng) ping 而不是讓客戶(hù)端表態(tài)網(wǎng)上很多方案是客戶(hù)端定時(shí)發(fā)一個(gè){type:heartbeat}給服務(wù)端服務(wù)端收到就更新lastSeen。這種做法能用但它有個(gè)隱患客戶(hù)端的定時(shí)器和網(wǎng)絡(luò)棧是獨(dú)立的即使鏈路已經(jīng)半斷開(kāi)客戶(hù)端的setInterval照樣觸發(fā)并調(diào)用ws.sendsend不報(bào)錯(cuò)并不代表數(shù)據(jù)真的到了對(duì)端。標(biāo)準(zhǔn)做法是服務(wù)端用WebSocket協(xié)議層的ping/pong控制幀。ws庫(kù)的底層會(huì)自動(dòng)響應(yīng)協(xié)議層的pong幀所以服務(wù)端只要定時(shí)ping然后統(tǒng)計(jì)這個(gè)周期內(nèi)有沒(méi)有收到pong就能精確知道TCP鏈路是否通著??刂茙蛔邩I(yè)務(wù)消息隊(duì)列比應(yīng)用層心跳更省資源、判定更準(zhǔn)。3.2 心跳代碼與參數(shù)間隔、誤判閾值、重連退避// heartbeat.js —— 基于 ws 庫(kù)的協(xié)議層心跳間隔 30s容忍 2 個(gè)周期無(wú)響應(yīng) const aliveSet new Set(); // 記錄“本周期內(nèi)回過(guò) pong”的連接 wss.on(connection, (ws) { aliveSet.add(ws); ws.on(pong, () aliveSet.add(ws)); ws.on(close, () aliveSet.delete(ws)); }); const HEARTBEAT_INTERVAL 30_000; // 每 30s 檢查一輪 const HEARTBEAT_TIMEOUT 60_000; // 距離上一次 pong 超過(guò) 60s 視為死亡 setInterval(() { for (const ws of wss.clients) { if (ws.readyState ! ws.OPEN) { aliveSet.delete(ws); ws.terminate(); // 直接掐斷觸發(fā)客戶(hù)端重連 continue; } if (aliveSet.delete(ws)) { ws.ping(); // 本周期有 pong繼續(xù)探活 } else { // 上一周期沒(méi)收到 pong說(shuō)明鏈路已經(jīng)斷了 ws.terminate(); } } }, HEARTBEAT_INTERVAL);這套邏輯的關(guān)鍵在aliveSet.delete(ws)的返回值每輪進(jìn)入定時(shí)器時(shí)如果這個(gè)連接在上一個(gè)周期內(nèi)回過(guò)pongdelete會(huì)返回true然后重新ping如果返回false說(shuō)明這個(gè)連接已經(jīng)整整一個(gè)心跳周期沒(méi)有回應(yīng)直接terminate。terminate和close的區(qū)別值得注意close是禮貌地走完關(guān)閉握手但TCP層可能已經(jīng)死了close發(fā)不出去terminate是直接銷(xiāo)毀底層socket立刻生效。服務(wù)端探活發(fā)現(xiàn)死連接就一律用terminate。參數(shù)別拍腦袋。30秒的檢查間隔和60秒的容忍閾值適合絕大多數(shù)內(nèi)網(wǎng)和公網(wǎng)場(chǎng)景但如果你在弱網(wǎng)環(huán)境比如移動(dòng)端經(jīng)常進(jìn)出電梯建議把間隔調(diào)到15秒容忍閾值保持2個(gè)周期不變。間隔太短會(huì)增加無(wú)謂的包量和CPU開(kāi)銷(xiāo)太長(zhǎng)則會(huì)讓用戶(hù)感知到「已斷線(xiàn)但重連遲遲不來(lái)」。另外服務(wù)端terminate之后不要馬上重連——客戶(hù)端收到onclose再發(fā)起重連這才是合理鏈路服務(wù)端不要替客戶(hù)端做重連決定。參數(shù)建議值說(shuō)明HEARTBEAT_INTERVAL30s弱網(wǎng) 15s兩次 ping 的間隔HEARTBEAT_TIMEOUT2 × interval連續(xù)兩個(gè)周期無(wú) pong 判定死亡服務(wù)端斷開(kāi)方式terminate不依賴(lài) TCP 層狀態(tài)直接銷(xiāo)毀客戶(hù)端重連退避1s → 5s → 15s → 30s 封頂指數(shù)退避避免斷網(wǎng)恢復(fù)時(shí)打爆服務(wù)端3.3 瀏覽器端的取舍原生 ping/pong 不可控走應(yīng)用層心跳瀏覽器里的WebSocket API沒(méi)有暴露ping/pong的控制能力你拿不到底層的pong事件。所以網(wǎng)頁(yè)端通常退而求其次采用應(yīng)用層心跳前端定時(shí)發(fā)一條業(yè)務(wù)心跳服務(wù)端更新lastSeen并用服務(wù)端的定時(shí)掃描兜底。這不算違反協(xié)議層心跳原則而是平臺(tái)限制下的務(wù)實(shí)選擇。應(yīng)用層心跳的收發(fā)兩端格式要對(duì)齊我常駐的字段是{ type: heartbeat, ts: 1717300000000 }前端每25秒發(fā)一次比服務(wù)端30秒的判定窗口略短服務(wù)端收到后只更新時(shí)間戳不往業(yè)務(wù)消息隊(duì)列里塞。要注意應(yīng)用層心跳消息不要把數(shù)據(jù)寫(xiě)進(jìn)Redis之類(lèi)的存儲(chǔ)里否則線(xiàn)上幾十萬(wàn)連接每分鐘會(huì)產(chǎn)生幾百萬(wàn)次寫(xiě)入純屬浪費(fèi)。// 前端瀏覽器端心跳LAS 網(wǎng)頁(yè)端 const HEARTBEAT_APP_LEVEL 25_000; let heartbeatTimer null; function startHeartbeat(ws) { stopHeartbeat(); heartbeatTimer setInterval(() { if (ws.readyState WebSocket.OPEN) { ws.send(JSON.stringify({ type: heartbeat, ts: Date.now() })); } }, HEARTBEAT_APP_LEVEL); } function stopHeartbeat() { if (heartbeatTimer) clearInterval(heartbeatTimer); } // 頁(yè)面卸載時(shí)一定要清定時(shí)器否則頁(yè)面關(guān)了還在空發(fā) window.addEventListener(beforeunload, stopHeartbeat);前端還有一個(gè)容易被忽略的點(diǎn)onclose事件的延遲。網(wǎng)絡(luò)斷開(kāi)時(shí)瀏覽器不一定立刻觸發(fā)onclose可能需要幾十秒甚至更久。所以前端不能只依賴(lài)onclose來(lái)啟動(dòng)重連更穩(wěn)的做法是同時(shí)監(jiān)聽(tīng)onerror和onclose并在每次發(fā)送消息失敗時(shí)也觸發(fā)一次重連檢查。重連時(shí)要把連接重新注冊(cè)一遍這一點(diǎn)后面第5章會(huì)專(zhuān)門(mén)講它是最常見(jiàn)的掉線(xiàn)恢復(fù)翻車(chē)點(diǎn)。4. 多端消息的路由從 A 端發(fā)起到 B/C 端到達(dá)連接和心跳都就緒后核心業(yè)務(wù)邏輯才上場(chǎng)一條消息從某個(gè)端進(jìn)來(lái)服務(wù)端決定往哪幾個(gè)端轉(zhuǎn)發(fā)。這個(gè)章節(jié)說(shuō)的不是某個(gè)具體業(yè)務(wù)而是LAS多端互通里通用的消息分發(fā)骨架。協(xié)議定得好不好直接決定后面接多少個(gè)業(yè)務(wù)類(lèi)型都不慌。4.1 消息信封與消息類(lèi)型先定協(xié)議再寫(xiě)代碼我習(xí)慣給所有WebSocket消息統(tǒng)一包一個(gè)信封而不是各業(yè)務(wù)發(fā)各的裸JSON。信封字段如下字段類(lèi)型說(shuō)明msgIdstring全局唯一用于去重與回執(zhí)typestring業(yè)務(wù)類(lèi)型如 las.template.update / las.task.statusfromstring發(fā)送者 clientIdtostring目標(biāo)clientId / roomId / broadcastpayloadobject業(yè)務(wù)數(shù)據(jù)tsnumber客戶(hù)端時(shí)間戳這個(gè)信封的好處是路由層只認(rèn)msgId、type、to三個(gè)字段完全不用關(guān)心payload里的業(yè)務(wù)結(jié)構(gòu)。后面每接一個(gè)新業(yè)務(wù)只需要新增一個(gè)type路由邏輯一行不用改。LAS業(yè)務(wù)里我至少會(huì)分成三類(lèi)實(shí)時(shí)同步類(lèi)模板變更、狀態(tài)流轉(zhuǎn)、指令類(lèi)強(qiáng)制刷新、踢下線(xiàn)、文件類(lèi)二進(jìn)制分片。一個(gè)type字段就可以區(qū)分這些不要讓路由層靠識(shí)別payload里的字段名做判斷。4.2 路由與回執(zhí)目標(biāo)離線(xiàn)時(shí)消息怎么辦路由層要做的事是解析to然后到userMap或roomMap里查出目標(biāo)連接逐個(gè)發(fā)送。如果目標(biāo)端不在線(xiàn)LAS消息必須有個(gè)落地方案否則這條變更就丟了。離線(xiàn)消息的策略我推薦「Redis List暫存 登錄后主動(dòng)拉取」而不是服務(wù)端無(wú)限期給每個(gè)離線(xiàn)用戶(hù)堆消息。// router.js —— 消息分發(fā)與離線(xiàn)暫存假設(shè) Redis 已通過(guò) ioredis 初始化 async function dispatchMessage(raw) { const msg JSON.parse(raw); const { msgId, type, from, to } msg; const targets resolveTargets(to); let anyDelivered false; for (const connId of targets) { const ws connMap.get(connId); if (ws ws.readyState 1) { ws.send(JSON.stringify(msg)); anyDelivered true; } } if (!anyDelivered) { // 目標(biāo)連接全不在線(xiàn)按 clientId 維度暫存最近 50 條 const key las:offline:${to}; await redis.lpush(key, JSON.stringify(msg)); await redis.ltrim(key, 0, 49); // 只保留最新 50 條防止堆爆 await redis.expire(key, 7 * 24 * 3600); // 7 天有效期兜底 } return anyDelivered; }resolveTargets需要處理三種to值clientId就展開(kāi)成userMap里的Set roomId就展開(kāi)roomMapbroadcast就直接返回所有在線(xiàn)連接。注意anyDelivered只代表「發(fā)出去了」不代表對(duì)端業(yè)務(wù)處理成功。如果需要端到端確認(rèn)由對(duì)端回一條ack消息服務(wù)端再更新消息狀態(tài)。這個(gè)ack環(huán)節(jié)在LAS里很重要尤其是桌面端改模板后手機(jī)端必須確認(rèn)收到光靠「發(fā)出去了」是不夠的。還有一點(diǎn)ws.send在底層socket緩沖滿(mǎn)時(shí)可能拋出異常。大文件消息尤其常見(jiàn)需要在send外面包try/catchcatch到就用terminate處理這個(gè)連接別讓異常影響消息循環(huán)里的其他連接。4.3 去重與順序同一個(gè)用戶(hù)的多個(gè)端別互相打架一個(gè)用戶(hù)三個(gè)端同時(shí)在線(xiàn)的時(shí)候最容易出現(xiàn)兩類(lèi)問(wèn)題。第一類(lèi)是消息重復(fù)桌面端發(fā)起模板更新服務(wù)端廣播給三個(gè)端手機(jī)端和網(wǎng)頁(yè)端各收到一次前端如果都做了彈窗提示用戶(hù)會(huì)看到兩條一樣的信息。第二類(lèi)是順序錯(cuò)亂桌面端先發(fā)了「開(kāi)始同步」又發(fā)了「同步完成」但由于兩條消息走了不同的實(shí)例或線(xiàn)程服務(wù)端可能把后面那條先發(fā)出去。去重方案是在服務(wù)端維護(hù)一份msgId的最近緩存。每收一條消息就把msgId塞進(jìn)Redis的SET并設(shè)置過(guò)期時(shí)間比如10分鐘重復(fù)的msgId直接丟棄。注意這里去重的是「同一事件」而不是「同一事件的多次廣播」廣播給三個(gè)端是業(yè)務(wù)需要的不沖突。順序問(wèn)題更頭疼單實(shí)例里可用一個(gè)簡(jiǎn)單的自增seq保證同連接的消息有序多實(shí)例場(chǎng)景下需要讓同一個(gè)clientId的消息始終進(jìn)同一個(gè)消息隊(duì)列或分片才能?chē)?yán)格保序。對(duì)LAS這種實(shí)時(shí)協(xié)作場(chǎng)景我通常只在同一連接維度保序跨端全局強(qiáng)一致投入產(chǎn)出比不高。// dedup.js —— 最近 10 分鐘的 msgId 去重 async function isDuplicate(msgId) { const key las:msgdedup:${msgId}; // setnx 成功說(shuō)明第一次見(jiàn)失敗說(shuō)明重復(fù) const ok await redis.set(key, 1, EX, 600, NX); return !ok; }去重放在路由之前。收到消息先查重復(fù)再走dispatch。一個(gè)看似小但實(shí)際很關(guān)鍵的細(xì)節(jié)msgId的生成不能在服務(wù)端統(tǒng)一生成而要由發(fā)起端生成。原因很簡(jiǎn)單用戶(hù)可能在桌面端先發(fā)出了消息但因?yàn)榫W(wǎng)絡(luò)沒(méi)到達(dá)服務(wù)端隨后手機(jī)端又發(fā)起一次同樣操作如果msgId是服務(wù)端生成的這兩條消息永遠(yuǎn)無(wú)法被識(shí)別為同一條。5. 多端互通排查5 個(gè)常見(jiàn)坑與現(xiàn)場(chǎng)處理辦法WebSocket踩坑的路徑高度重復(fù)以下五條每一個(gè)我都實(shí)打?qū)嵱龅竭^(guò)現(xiàn)象、原因和解決辦法按順序?qū)懩憧梢詫?duì)照著手里的日志排查。5.1 Nginx 靜默掐斷空閑連接現(xiàn)象客戶(hù)端連接建立后隔一段時(shí)間恰好是60秒左右就收到onclose服務(wù)端日志里沒(méi)有任何close記錄。原因Nginx作為反向代理時(shí)默認(rèn)proxy_read_timeout是60秒在這段時(shí)間內(nèi)如果后端沒(méi)有數(shù)據(jù)返回Nginx會(huì)主動(dòng)斷開(kāi)連接。WebSocket的連接恰恰大部分時(shí)間沒(méi)有數(shù)據(jù)流動(dòng)于是被當(dāng)成空閑超時(shí)掐斷。解決在Nginx的location里顯式關(guān)閉代理超時(shí)。location /ws/ { proxy_pass http://las_ws_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; proxy_send_timeout 3600s; }注意proxy_set_header Connection那行必須寫(xiě)成upgrade否則WebSocket握手在Nginx這一層就失敗。這個(gè)坑的癥狀是連得上但馬上斷開(kāi)和心跳無(wú)關(guān)。5.2 心跳間隔不一致導(dǎo)致誤殺現(xiàn)象客戶(hù)端明明在線(xiàn)卻頻繁被服務(wù)端斷線(xiàn)重連。原因服務(wù)端心跳判定閾值設(shè)的30秒客戶(hù)端的應(yīng)用層心跳發(fā)的倒是挺勤但客戶(hù)端所在的網(wǎng)絡(luò)環(huán)境有丟包pong幀偶爾沒(méi)回來(lái)連續(xù)兩個(gè)周期沒(méi)收到pong就被service端誤殺。解決把服務(wù)端的容忍閾值從2個(gè)周期放寬到3個(gè)周期同時(shí)讓客戶(hù)端的應(yīng)用層心跳間隔比服務(wù)端探活間隔短至少5秒留出余量。誤殺重連不是大事但每次誤殺都會(huì)帶來(lái)一次重連風(fēng)暴連接數(shù)多了會(huì)產(chǎn)生雪崩效應(yīng)這個(gè)參數(shù)值得多調(diào)幾輪。5.3 斷線(xiàn)重連后消息繼續(xù)發(fā)給舊連接現(xiàn)象用戶(hù)手機(jī)切了Wi-Fi再切回來(lái)連接斷了又重連成功但之后服務(wù)端發(fā)的消息他總是收不到。原因前端重連后只建立了新的TCP連接沒(méi)有重新發(fā)起注冊(cè)握手服務(wù)端userMap里用戶(hù)的connectionId還是舊的消息全發(fā)給了已經(jīng)死掉的舊連接。解決把「連接建立」和「連接注冊(cè)」做成兩個(gè)明確的階段前端必須在onopen之后等待注冊(cè)響應(yīng)服務(wù)端注冊(cè)成功再收業(yè)務(wù)消息。最常見(jiàn)做法是重連后第一條消息一定是register。// 客戶(hù)端重連后必須重新 register不能只 new WebSocket() function connectWithRegister() { const ws new WebSocket(wss://las.example.com/ws?clientIdU10086); ws.onopen () { ws.send(JSON.stringify({ type: register, clientId: U10086 })); }; }服務(wù)端把register消息放進(jìn)用戶(hù)白名單沒(méi)注冊(cè)的連接拒絕轉(zhuǎn)發(fā)業(yè)務(wù)消息。這個(gè)約束能直接避免重連后消息丟失的黑匣子問(wèn)題。5.4 多端在線(xiàn)時(shí)的消息重復(fù)與回顯問(wèn)題現(xiàn)象A端發(fā)一條消息B端、C端都收到了但A端自己也收到了一份服務(wù)端回顯前端沒(méi)有過(guò)濾界面上出現(xiàn)兩條自己發(fā)的消息。原因廣播邏輯沒(méi)有排除發(fā)送者連接或者前端沒(méi)有對(duì)本地發(fā)送的消息做ack去重。解決服務(wù)端廣播時(shí)排除from的connId前端也最好把「自己發(fā)出的消息」直接渲染成pending狀態(tài)收到ack再變成已送達(dá)而不是等廣播回來(lái)再渲染。LAS里桌面端和網(wǎng)頁(yè)端經(jīng)常共用一個(gè)賬號(hào)回顯去重尤其要注意。5.5 Sending on closed socket 異?,F(xiàn)象服務(wù)端日志頻繁出現(xiàn)Error: Sending on closed socket偶發(fā)進(jìn)程崩潰。原因連接在ws.send之前剛被關(guān)閉但connMap里還殘留引用代碼直接往已關(guān)閉的連接上寫(xiě)數(shù)據(jù)。解決發(fā)消息前檢查readyState 1只是第一道保險(xiǎn)還要在send外面包try/catchcatch住就直接清理連接索引。不要小看這個(gè)錯(cuò)誤流量高峰時(shí)它會(huì)拖垮整個(gè)消息循環(huán)屬于高發(fā)事故源。// safeSend.ts —— 帶兜底的發(fā)送封裝 function safeSend(ws, raw) { try { if (ws ws.readyState 1) ws.send(raw); } catch (e) { // 連接已死清索引并終止 connMap.delete(ws.connId); ws.terminate(); } }6. 進(jìn)階多實(shí)例擴(kuò)展與端到端驗(yàn)證單機(jī)跑通只是開(kāi)始LAS多端互通要上生產(chǎn)單實(shí)例撐不住所有在線(xiàn)連接橫向擴(kuò)展是繞不開(kāi)的問(wèn)題。一個(gè)用戶(hù)連在實(shí)例A另一個(gè)用戶(hù)連在實(shí)例B兩個(gè)實(shí)例之間的連接互相不知道對(duì)方消息就斷在中間。常見(jiàn)做法是引入Redis Pub/Sub作為實(shí)例間消息總線(xiàn)本地路由直接發(fā)本機(jī)連接跨實(shí)例消息通過(guò)Redis發(fā)布所有實(shí)例都訂閱同一個(gè)頻道收到后檢查目標(biāo)連接是否在自己這里。// cluster.js —— 多實(shí)例橋接本地直接路由跨實(shí)例走 Redis 廣播 const sub new Redis(); // 訂閱連接 const pub new Redis(); // 發(fā)布連接 sub.subscribe(las:ws:cluster); sub.on(message, (_channel, raw) { const envelope JSON.parse(raw); // 只有目標(biāo)連接在本實(shí)例才處理避免 A 實(shí)例收到又轉(zhuǎn)發(fā)回 B 實(shí)例 dispatchMessage(envelope); }); function sendCrossInstance(targetConnId, msg) { pub.publish(las:ws:cluster, JSON.stringify({ target: targetConnId, msg })); }端到端驗(yàn)證我習(xí)慣用Node腳本模擬多端同時(shí)在線(xiàn)而不是靠手工開(kāi)幾個(gè)瀏覽器窗口戳來(lái)戳去。用ws庫(kù)起一個(gè)測(cè)試客戶(hù)端同時(shí)模擬桌面端、網(wǎng)頁(yè)端、手機(jī)端三個(gè)身份連到同一個(gè)clientId下然后讓一端發(fā)消息斷言另外兩端都能收到再手動(dòng)調(diào)低心跳閾值驗(yàn)證斷線(xiàn)重連。// test.js —— 模擬 100 個(gè)并發(fā)端做聯(lián)調(diào) const WebSocket require(ws); function createTestClient(clientId, port 8080) { const ws new WebSocket(ws://127.0.0.1:${port}/ws?clientId${clientId}); ws.on(message, (data) { const msg JSON.parse(data.toString()); if (msg.type las.template.update) { console.log([${clientId}] 收到模板更新:, msg.payload.version); } }); return ws; } // 同時(shí)模擬 100 個(gè)用戶(hù)在線(xiàn) const clients Array.from({ length: 100 }, (_, i) createTestClient(U${10000 i}) ); // 等 2 秒連接全部建立再?gòu)?U10000 廣播一條模板更新 setTimeout(() { clients[0].send(JSON.stringify({ type: las.template.update, to: broadcast, payload: { version: v2.3.1 } })); }, 2000);跑這個(gè)腳本時(shí)重點(diǎn)觀察兩個(gè)指標(biāo)一是100個(gè)連接同時(shí)注冊(cè)時(shí)服務(wù)端有沒(méi)有內(nèi)存突增或報(bào)錯(cuò)二是廣播后是否每個(gè)端都收到了且只收到一次——重復(fù)也說(shuō)明路由有問(wèn)題。我自己的教訓(xùn)是多端互通上線(xiàn)前一定要專(zhuān)門(mén)做一次「殺掉服務(wù)端」的演練看客戶(hù)端重連能不能在30秒內(nèi)全部恢復(fù)賬號(hào)信息會(huì)不會(huì)因?yàn)橹剡B而丟。這個(gè)演練花錢(qián)最少、救急最多。LAS多端互通的實(shí)現(xiàn)鏈條就是這樣連接注冊(cè)、心跳判定、消息路由、多實(shí)例橋接每層都守住邊界端和端之間才能安靜地實(shí)時(shí)同步。希望這些踩出來(lái)的經(jīng)驗(yàn)幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
日韩美女高潮喷水视频| 91老熟妇| 美女尤物人人操| 爱干爱射网啊啊啊| 日本欧美中文字幕| 亚洲国产欧美日韩精品一区二区三区,国产一区二区三区在线看片,欧美性猛交 XXX | 色麻豆AV| 麻豆国产精品午夜视频| 欧美AB在线观看| 日本女人久久久| 国产成人自拍视频在线| 日本黄色天堂| 欧美99热| 欧州一区二区三区四区| 97操97色| 国产黄色剧情影片麻豆免费播放| 91校园春色长篇| 国产精品不卡少妇白| 国产AV久久久蜜爱影集| 9I1性色影院| 偷窥自拍亚洲天堂网爆| 久久久久久久久久久久色网| 婷婷91| 国产又长又大又粗的视频| 日韩探花精品在线视频| 夜夜免费视频| 日韩亚洲Av人人夜夜澡人人爽| 美女丝袜激情小说| 97人人操人人摸人人爱| 精品二区三四区五电影| 99热色精品| 国产麻豆91欧美一区二区久久婷婷国产精品| 欧美亚洲另类在线蜜桃| 97久久超碰国产精品| 亚洲经典啪啪| 久操电影| 久久久久亚洲精品| www久久久| 精人妻一区二区三区| 国产超碰人人操| 亚洲欧洲综合| www四虎| 最新无码国产| 久久久内射良家| 色九月婷婷| 搡老女人老91妇女老熟女| 老熟女91av| 啪啪啪东京| 风月影院男女十八禁| 操逼网站视频漫画国产| 欧美人与动性人交a| 爱射综合| 色黄色美女大长腿午夜视频| 久久久无码精品人妻二区| 另类图片五月天| 亚洲精品久久久久久久蜜桃臀| 黄色污污污污污污网站| 嫩草美女久久| www.婷婷六月天| 99999国产精品| 欧美美女啪啪视频| 手机在线视频国内精品| 色色九区| 久久m| 色五月亚洲| 91免费看一区二区三区| 亚洲国产青青| 欧美日韩m| 老熟妇一区二区三区…| 蜜臀久久99精品久久久久久无删减| 操逼视频亚洲| 国产精品一区二区三区免费视频| 婷婷五月天无码| 性做久久久久久免费观看软件| 欧洲综合色| 中文字幕制服欧美久久一区| 激情AV| 91搡老女人老妇女老熟女歌词翻译| 中文字幕乱碼在线| 久久人妻视频| 中文字幕亚洲永久精品| 成·人免费午夜在线观看| 超碰综合色| 69精品人人人人| 国产av激情无码久久天堂| 精品女同一区| 婷婷久久久精品| 亚洲国产成人福利在线观看| 97操| 欧美日本不卡在线| 欧美,日韩,中文,另类| 夜夜夜夜夜夜夜夜夜狠狠狠狠狠狠狠| 日韩精品一区的| 一本色道综合久久欧美| 超碰在线91| 国产成人主播| 精品国产网站| 啊啊啊啊嗯嗯嗯用力好爽| 狠狠操夜夜| 97免费视频在线| 青青草国产一区二区三区| 白丝AV网站| 丁香久久| 日韩中文字幕二区| 激情久久久| 久久av成人无码免费| 狠狠婷婷亚洲中文综合久久| 这里都是精品| 国内外激情在线| 伊人伊人LD| 欧美性天天影视| 91n免费处女| 一区二区偷拍拍视频| 99色网| 欧美日韩国产色五月综合在线| a人欧美综合天堂麻豆| 91一区二区| 久久久久久久久成人av解说| 无码丰满熟妇一区二区浪潮AV| 富女玩鸭子一级毛片| 欧美亚洲今日在线| 亚洲欧美国产日本一区二区三区| 伊人操你| 亚欧高清| 色在线视频导航| 亚洲人妻日日日| 性欧美| 青青欧洲黑| 96爱综合| 国产黄色动态精品| 东京热一区二区三区四区五区六区| 激情五月婷婷综合| 超碰日本97美女人妻人人玩人人爱 | 亚洲综合20p| 亚洲色图欧美激情| 97国产精品| 亚洲av青草久久一区二区| 欧美劲爆第一页| 97干在线视频| 岛国在线国产| av天堂5| 青青色在线观看| 美女91AV| 亚洲影院365| 人人模人人看| 日本欧美一区二区三区视频麻豆| 国产91乱伦| 乳欲人妻办公室奶水| 3P乱轮视频| 国产精品午夜高潮呻吟久久av| 免费啪啪一级视频| 91视频国品一二三区| 久7色| 五月天色图影视| 色婷婷aV一区二区三区麻豆综合| 岛国人妻少妇av在线观看| 天天天天做夜夜夜夜做| 精品妇操一区二区三区| 噜噜噜噜天天狠狠| 日韩无码极品| 中文字幕亚洲永久精品| 色婷婷电影网| 久草综合京东| www被窝色com| 亚洲一区二区av| 成人一二| 亚洲黄色a级片| 成人日本视频人妻在线| 97色在线观看| 国产熟码AV| 亚洲精品国产拍免费91在线| 中文字幕天堂在线| 久久99午夜精品一区人妻| 久久激情视频| 久草资源在线视频官方总站日韩丝袜美腿 | 神马久久久久久久久久久久| 呻吟 欧美 日本 中出| 久久久久久综合久久伊人蜜月| 99久久99久久免费精品蜜臀| 国产中文字幕曰本毛片| 狠狠 91| 东北女人被操| 亚洲天堂男人天堂| 日本精品无码三级网站| 人妻夜夜爽天天爽麻豆三区网站| 欧美丝袜美女电影一二三四区| 99色在线| 人妻二区| 国产精品大香蕉| 97超碰色屌| 91日韩网站| 人人弄人人摸| 色吧五月| 久久久国产精品亚洲精品| 久操免费观看| 国产一级作爱毛片| 9精品久久| 亚洲欧美日韩中文播放| www久久久| 人妻 欧美 中文| 国产精品久久久久婷婷二区次| 免费1级a做爰片观看| 在线黄页看毛片| 夜夜夜夜爽| 久久这里只精品免费福利| 久久久久婷婷| 欧美久久人妻少妇一区二区| A级在线视频| 免费在线观看AV无码网站| 少妇同性| 精品一级毛片在线观看| · —级AA伦aa坐爱午夜极速ⅴA一区天天噪天天噪天天噪 | 啪啪91| 啊啊啊在线看| 视频在线观看免费一区二区三区| 精品人人| 懂色aV一区二区天美传媒| 日韩欧美国产高清视频| 超碰久久网| 免费少妇一区二区| 江都AV在线| 东北熟女91| 爽 好舒服 无码刺激久久| 人人超碰在线观看黄| 久久久久国产精品久久久| 久久人人看| 欧亚韩国999| 91爆操视频| 97一区二区三区视频| 尤物av网站免费在线播放| 999狠狠综合| 快灬快灬 一下爽蜜桃在线观看| 人妻aa| 欧美黑人91| 久久男女激情视频网站| 四虎免费在线播放| 熟女被操视频网址| 国产精品伦理| 玖玖在线视频| 丰满人妻一区二区三区色-百度| 精品久久99| 大香蕉日韩| 97香焦色区| 媚薬在线视频麻豆| 日韩 欧美 另类 人妻| 91强在线播放| 无码免费精品高清| 9久9久| 欧美做爰无码A片视频| 人乳av| 欧美视频边做饭边橾| 欧美综合色综合| 96久久精品一二三区色欲| 99热国产| 日本三级日本三级三级人妇四虎| 熟女这里只有精品6| 天堂麻豆天美| 人人摸人人摸人人干| 欧美另类天堂| 久久人妻办公室视频| 蜜臀久久久99久久久久| 伊人久久大香线综合无码| 日本1区2区不卡视频| 欧美综合网1| 亚洲美女自拍偷拍视频| 暴力av在线| 日韩乱码av| 一级AV性爱| 色制服丝袜夫妻av一区| 成人看片网站| 激情小说日韩无码| 欧美第一页| 激情五月天网| 欧美成人A天堂片在线观看| 亚洲在钱| 四虎永久在线精品免费网址| 天天干干天天干干| 婷婷激情四射| 97精品视频网站| 少妇滛荡视频| 97在线视频观看网站| 九九热午夜欧亚国产视频| 屌色在线97视频| 高清无码久操视频| 久久久久久十| 少妇69中文| 欧美日韩中文亚洲v在线综合| 亚洲欧美综合网| 红桃视频高潮| 亚洲精品久久久久久久蜜桃臀| 色悠久| 亚洲综合伊人| 亚洲官网在线| 激情五月丁香五月| 天天操夜夜嗨| 日本不卡一区| 久久婷婷一区| 天堂综合| 一本一首道人妻少妇免费久久| 自偷自拍的亚洲视频| 伊人专区一区二区三区| 78精品| av线电影| wwe 天天干.com| 丁香五月综合| AA特级绝黄| 欧美传媒| 少妇一区二区三区| 欧美三四五区| 精品人妻一区春色| 欧美色图私拍91| 水野优香在线观看| 免费一级视频特黄色大片| 秋霞一级A片黄色视频| 99re视频这里只有精品| 久久精品国产97欧美精品亚洲| 伊人一区二区三区| 99.色网| 一区在线观看中文字幕| 约操熟妇| 中文字幕亚洲热播人妻| 澳门黄片一香蕉视频| 91丝袜视频在线观看| 啊嗯嗯啊好大好爽| 精品人妻一区二区三区视频| 91在线色| 97色插| 95人妻爽爽人人做人人澡 | 日韩欧美大片免费高清啪啪| 在线不欧美| 午夜啊啊| 久9爱精品| 天堂精品一区| 欧美中字不卡| 精品乱码在线观看| 学生妹天天看| 婷婷五月天无码 | AV污污污污| 亚洲精品国产无码高清| 另类亚洲一区二区三区| 无码不卡亚洲成?人片| 91爱网| 久九九九九九九九热| 色777999综合| 男人的天堂久久| 九九五月天| 日韩电影中文字幕| 9 1果冻精品视频| 久久禁| 91四海无码日韩欧美| 亚洲色综网| 久久久96精品| 中文字幕一区二区无码成人| 91精品人妻一区二区三区蜜臀| 亚洲av资源| 久久一区二区蜜桃| 思思热国产高清| a'v在线资源| 一级片视频啪啪| 51久久夜色精品国产麻豆| 欧美亚洲素人制服精品| 免费观看国产小粉嫩喷水精品午| 日本免费人成视频播放120秒| 日婷婷| av在线不卡一区二区三区| 中文字幕亚洲永久精品| 婷婷视频网| 亚洲精品一区二区精品| 日韩亚洲国产视频| 免费一级毛片在线视频观看| 大香蕉男女超碰精品在线| 久久久蜜桃一区二区三区| 人妻激情另类| 麻豆福利视频导航| 国内97干免费看| 33044男人的天堂深夜备| 综合亚洲欧美| 久久成年片色大黄全免费网站| 在线观看不卡一区二区三区| 日韩精品永久在线观看| 99热在线播放| 动漫片子网站3黄| 日韩精品怡红院| 人人妻人人色一区二区三区| 少妇被c 黄 免费观看| 91在线秘 男同| 欧美经典一区二区三区 | 人妻少妇一区二区| 色综合加勒比四四季| 国产女人9999| 久久久久久性爱免费视频| www.亚洲黄色| 综合久久婷婷| 骚逼一区二区| sewuyueav| 老外又粗又长一晚做五次| 免费啪啪一级视频| 女人的久久久| 亚洲素人综合| 欧美福利视频啊啊啊啊| 免费一级欧美片片线观看| 无码久| 96AV久久久| 精品制服美女中文一区二区三区| 色网站导航大全| 国产精品自产拍在线观看社区| 久久久久久久 九九九九九九九 | 亚码人妻| 96久久久| 激情看片网站| 97 九色| 激情小说亚洲| 99啪啪视频| a人欧美综合天堂麻豆| 蜜臀久久99精品久久久久电影| 国产成人超碰在线| 天天综合~91入口| 91n.欧美| 国产精品极品美女视频| 国产精品经典一卡久久久| 亚洲欧美啪啪| 国产成人精品必看| 亚洲熟女国产综合另类| 97久久超碰国产精品| 在线A日本| 亚洲AV资源| 97伊人网| 久久久夜夜嗨免费视频| 中文字幕在线2| 日日操免费视频| 国产11页| 亚洲动态色图| 超碰人人色| 亚州大图综合色图| 三级特黄60分钟播放| 综合色图,成人综合网| 亚洲欧美变态| 国产1769在线| AV色五月天| 在线精品福利免费播放| 色播五月丁香| 亚洲久久天堂| 国模精品娜娜一二三区| 天天操天天7| 亚洲图片激情综合另类| 免费网站观看www在线观| 天天澡天天爽日日AV| 国产精品麻豆成人AV艾秋| 麻豆色约约| 丝袜熟女一区二区三区| 久久一区二区加油站| 狠狠中文字幕| 超碰久久网| 911av网站免费观看| 人人澡人人弄| 日本三级网页| 亚洲另类色综合网站| 破苞ⅩXXX性无码动漫无码| 高清不卡 中文 人妻| 91爆操视频| 啊啊啊啊啊舒服| 国产呦精品一区二区三区下载| 视频在线中文字幕| 欧美日韩性爱精品| 97在线视频网站| 人妻天天夜夜爽一区二区| 亚洲97超碰| 啊啊啊 在线观看| 张柏芝国产一区在线观看| 日韩伦理久 久久 清纯| 欧美大波激情xxxx| 人人操人人射人人干| 亚洲最大网站av| 日韩91网| 九九久久一区二区三区| 亚洲天堂一区二区久久| 丝袜高跟澳门91视频| 久精品无码av一区二免费国产在线观看 | 青娱乐啪啪视频| 99.色网| 91搞逼视频| 91艹| 亚洲高潮少妇| 三级精品三级在线观看| 精品视频久久区| 极品极品色影院| 亚洲天堂资源网| 青青草吊丝| 手机在线视频国内精品| 久久亚洲一区女同性恋中文字幕| 91九九九馒头| 国产精品呦一区二区三区| 精品人妻视频一区二区在线播放| 婷婷五月天影院| 久久久久久久强迫| 日韩 欧美 国产 麻豆| 91精品黄在线观看| 无码操逼视频一下| 欧美97av| 亚洲日韩青青草色月| 亚洲欧美国产成人综合不卡| 啊啊啊啊啊啊在线观看| 欧美国产操逼| 男人天堂婷婷五月天校园春色| 国产欧美日本亚洲精品| 熟女高潮精品一区二区| 91嫩草欧美| 操婷婷逼| 亚洲图片日本AⅤ欧美在线| 婷婷精品久久av影视| 麻豆国产原创AV色哟哟| 97摸视频| 伊人操你| 欧美美女视频| 超碰97亚洲区| 2025亚洲男人天堂| 九九人人操| 国产日韩区| 欧美黑人熟妇精品91| 91老熟女老女人国产老太| 亚州国产精品乱| 无码日韩人妻av一| 日韩国产精品人妻无码久久久| 91n.欧美| 欧美78| 91女人的网站| 激情婷婷五月天| 欧美经典一区二区三区| 精品久久无码午夜福利 | 99热这里都是精品| 国产探花日韩援交| 日韩一二三区| 亚洲成人在线资源| 久青草影院| 亚洲无码国产探花在线观看| 色路综合| 嫩草 我啊~嗯~在线| 久草资源在线视频官方总站日韩丝袜美腿 | 伊人久久亚洲中文字幕| 超碰人妻在线| 国产精品自产拍在线观看社区| 午夜福利1区2区3区| 91成人18| 高清无码人妻久久久一区二区三区aⅴ| 久久久国产精品亚洲精品| 大香蕉 222| 一本道综合色图| 精品少妇一区二区三区在线视频| 搡老女人老妇女AAA一VU麻豆| 香蕉国产精品麻豆亚洲欧美日韩| 国产品精品自在在线午夜免费| 久久三区四区| 97超碰精品图片| 青青草原av| 欧美综合自拍亚洲综合图| 亚欧美综合网。| 欧美青青视频| 成人欧美日超碰| 精品九九九九九九九九九| 超碰 av 女人天堂| 97干天天| 色香在线| 91女优在线观看| 秋霞鲁丝午夜无码一区二区三| 中 文字幕一区二区三四 五 区日 日 骚 | 熟女乱3伦999| 中文字暮97| 东京热天堂网| 国产精品96| 欧洲精品一级二级精品综合视频综合| 97国产|免费| 综合色区偷拍| 屁股久久久久久久| 国产粉嫩蜜臀av一区二区三区| 国产精品电影大全| 欧洲亚洲国产综合在线| 巨爆乳一区二区爆乳区| 91碰超| 久操网址| 综合欧美日本三级| 人妻少妇久久久| 91N欧美| 欧美中文字幕一区| 97就爱干| 亚洲欧洲综合| 高清在线不卡一区二区 视频| 三级日韩一区二区三区| 亚洲av影音先锋| 久久婷色| 狠肏骚人妻| 久草精品视频| 91美| 91性高朝久久久久久久久| 色欲无码人妻日韩欧美精品| 日本肏逼视频在线观看| 最新加勒比丝袜在线| 艳尻美人妻| 91在线丝袜| 九色黄站| 乱伦av.com| 久久女婷| 人妻内射一区二区在线视频| 精品日日人妻| 久久国产性爱| 插入综合网| 久久夜精品一区二区三区| 国内一级精品| 国产一区在线观看无码AV | 亚洲免费日韩在线一区二区| 偷拍亚洲情色| 亚洲一区操| 五月丁香啪| 天天综合网1| 91一区二匹| 97摸视频| 欧美久久婷婷| 久久专区| 91麻豆va国产精品| 夜夜骑天天燥| 超碰在线人人射| 日本片日本片祼观看网站在线看中文版网页在线看 | 99热在线播放| 国产中文字幕曰本毛片| 干b在线性社区| 日本韩国五十路六十路七十路老熟女作爱视频网站 | 浪人综合网| 亚洲丝袜B诱惑| 久久久精精精| 国产 三级自拍| 天天看片麻豆| AV天堂国产| 色婷婷久久| 伊人午夜福利视频| av网页一区二区三区| 婷婷五月天久久精品视频一区二区三区| 久久一二三四五六七八九区| xxxx网站亚洲精品| 亚洲自拍欧美国产首页网曝| 狠狠婷婷亚洲中文综合久久| 亚州精人品大香蕉| 午夜啊啊| 五月天激情四射| 四虎精品亚洲| 岛国成人av在线播放网址| 是还免费视频1727我| 欧美1区二区三区公司| 国产13区| 亚洲成人精品在线一区| 青青草原综合久久大伊人精品| 好吊色青靑草| 亚洲欧洲偷拍一区| 超碰色综合| 校园春色 男人天堂| 精品免费囯产一区二区三区 | 精品无码一区二区| 探花视频免费观看国产专区| 美女黄页| 无码人妻一区二区三区色欲aⅴ| 青青操97| 国产9 9在线 | 亚洲| 操b网站亚洲无码| 亚洲天堂一区二区久久| 99只有精品| 一本一道vs波多野结衣| 老鸭窝在线视频播放| 中国亚洲呦女专区| 久久人妻熟女一区二区 | 人妻一区二区三区四区视频| 玖玖蜜臀资源网| 在线播放免费av福利片| 欧美与日韩97| 色色操| 17c嫩草51久久91嫩草| 色女网日韩| 国产精品无码av嫩草| 国产AB视频| 婷婷五月成人| 高清无码久操视频| 97热视频在线观看| 综合色99| 在线综合网| 99热精品国产| 亚洲精品精品一区二区| 欧美乱欲| 久日综合网| 这里只有精品视频在线| a片久久久久久久久久久久| 欧美91网站| 五月婷婷六月天| 激情小说五月天| 国产农村妇女精品一| 国产欧美日本亚洲精品| 物业黑人 AV一区| 丁香五月综合| 亚洲精品国产熟女| 变态综合色| 亚洲欧美日产国产91毛片| 一级久久久久久久久久久| 国产传媒一区二区三区| 欧美日韩亚洲五月天婷婷| 噜噜噜狠狠色综合| 高潮毛片无遮挡高清免费| 91制服丝袜| 男人 天堂 日 亚洲| 91九色精品熟女内射| 吖在线不卡一区二区国产剧情| 亚洲国产97在线精品一区| 精品久久久久瑟瑟| 99色在线视频| 污污汅18禁网站在线永久免费观看| 亚洲小说视频| 91色s| 欧美高清性猛交| 开心五月深爱五月| 大色综合网| 免费观看性欧美一级| 亚洲自拍97| 国产精品久久久午夜夜伦鲁鲁| 2019天天操天天爽天天拍| 五月婷婷六月激情| 翔田千里av一区二区三区| 免费观看国产小粉嫩喷水精品午| 97干天天| 五十路六十路素人熟女| 无码78| 精品久操| 啊啊啊啊啊啊啊在线| 色第一页| 亚洲丝袜天堂| 蜜臀在线免费观看在线免费观看| 日韩三级一区| 无码又爽又硬又激情免费视频| 激情接吻视频久久久久久| 久思思热视频在线观看| 国产久久免费精品视频| av激情亚洲五月天| 97干色| 好吊色青靑草| 超碰美国| 91综合站| 97在线观看免费视频| 人人操人人肉久久精品| 校园春色AV天堂| 国产精品一区二区麻豆| 中文字幕午夜精品久久久| 夜色97| 久久精品99久久久久久| 国偷自 一区二区| 校园春色家庭伦理欧美激情| 黄久在线| 免费男人的天堂| 91天堂丝袜美腿| 欧美午夜熟妇黑人精品91| 亚洲精品国产拍免费91在线| 少妇的嫩逼图片| 999精品乱码| 啊啊啊操死我| 韩国三级一线观看久| 日韩av电影成人在线| 欧美性爱无码一区二区三区| 视频黄色国产一级| 婷婷AV一区二区三区| 色婷婷久久| 国产少妇肉丝在线观看| 亚洲天堂日本| 日韩一区二区熟女| 丰满人妻一区二区三区在线| 超碰97在线 欧美 国产| 熟女AV一区| 欧美体内射精| 2017天天插| 乱性AV| 日本免费一级AAA大片器| 久久久久久国产精品免费网站| 中文字幕av乱伦| 大香蕉碰碰| 天天影视射综合网| 日本精品加勒比海一区| 福利操逼| 4虎在线视频| 自拍六区| 欧美一区二区福利在线| 性爱av网站| 久久亚洲影院一区二区| 极品久久久久久久久久久久久久| 91成人亚洲色图| 中文字幕av亚洲精品| 最新的亚洲无吗| 日本特黄f c2| 伦理日韩国产久久| 日韩无码一区二区三区| 国产AV毛片| www.狠狠干.coom | 精品亚洲黄色片 国产精品导航一区二区| 91 亚洲 欧美 日韩 国产 综合| 91oumei| 走光一区92下载| 日韩精品人妻| 久久99精品视频| 免费网色网站| 蜜臀视频网站| 免费精品福利在线观看| 久草资源在线视频官方总站日韩丝袜美腿| 久久噜噜噜精品国产亚洲综合| 国产乱伦视频污| www色日本| 夜夜国产一区| 秋霞色色影院| 天天天天天干夜夜夜夜夜操| 蜜桃精品视频一区| 视频一区二区免费在线| 免费观看啪视频| 欧美黑人极品高潮喷吹熟女黑人性暴力日韩在线欧美极品一区二区老师 | 日韩日韩日韩-国产乱码精品一区二区| 亚洲另类欧美精品| 69人妻精品一区二区绯色| 97视频在线视频| 亚洲熟女乱色一区二区三区| 女人爽到高潮久久久| 国产黑白丝在线| 黄片色区软件| 欧美 牲| 日韩欧美操逼xxx| 国产日本熟女顶级一区二区三区视频 | 97 视频在线| 国产精品白领在线观看 | 黑丝自慰喷水网站| 日本精品国产视频| 人妻一区二区三区四区视频| 日本有码久久| 美女t无毒不卡不卡| 天天看,天天做| 九九九九九九免费视频| 太久视频| 内射黑丝袜| 国产精品一区二区三区,亚洲综合| 日韩激情视频| 十八禁av无码免费网站APP| 超碰在线974| 人人操,人人插| 国产精品网站免费| 国产男女边吃边摸视频网站| 亚洲官网在线| 嫩呦国产一区二区三区AV| 日逼五月天| 日韩欧美成人午夜福利| 蜜臀久久99精品| 久久一区二区高清免费| 韩国午夜理伦三级好看| 丝袜综合| 免费αV在线视频| 一区二区 电影 亚洲| 波多野结衣被操50分钟免费视频| 久久久久久久久久久999| 成全在线观看免费观看| 香蕉免费一区二区三区不读| 探花在线免费观看视频国产一区| 久久影视二区三区行押| 岛国精品视频在线观看| juliaann欧美丝袜办公室| 伊人综合色网| 日本熟女不卡视频| 不卡一区视频| 五月丁香色情| 亚洲无码com| www.高清无码诱惑一区.com | 久久久久久九九九| 91色五月俺来也| 青娱乐亚洲自拍| 四虎影视国产精品| 在线观看十八禁| 国产一级特黄大片处女| yazhouzaixian| 91大胆欧美| 日韩免费在线视频观看| 久热网| 少妇蜜汁| 欧美顶级黄色大片免费| 九九久久久| 狠狠亚洲| 激情婷婷五月天| heyZO天然素人无码AⅤ专区| 白嫩91在线亚洲| 1024亚洲中文字幕久在线看片你懂的| 日韩有码专区| 成年人性爱日韩| 久久二| 欧美夜夜骑视频| 五月天激情国产综合婷婷婷| 日本网色| 污啪啪啪视频| 操逼视频色| 欧美日韩制服| 色娱乐色呦呦夜夜夜夜av| 五月丁香六月| 免费亚洲黄色视频在线观看| 97chaopengongkai| 色阁阁AV综合网| 欧美黑人性猛交91| 久久久久国产一区二| 自拍偷拍 日韩欧美| 天干天干天干天天做| 一区 欧美 日韩 麻豆| 久久五月视频| 操逼国产免费| 香港澳门日本三级网站| 欧美午夜熟妇黑人精品91| 日韩钢筋无码高清啾啾啾| 中出91| 国产小黄片在线免费观看 | 日韩AV无码中文一区二区| 欧美色宗合| 风间由美日韩欧美久久| se,,,亚洲欧美| 日韩AV色图| 女色视频社区| 99久久九九| 美女黄频a美女大全免费皮| 午夜福利1区2区3区| 久久午夜色播影院免费高清| 一本色道久久综合狠狠操| 欧美少妇性乱| 伊人色综合超碰| 又大又黄国产| 日本超碰在线国产一区| 超碰在线看| 免费观看啪视频| 91动漫操逼视频| ..日韩av毛片精品久久久| 久草精品国产99| 亚洲国产另类在线中文| 伊人久久AV诱惑悠悠| 东京热av影院| 午夜啊啊| 深喉吞精| 唯美清纯 妖精视频| 综合亚州欧美| 性高潮久久久久久久久久久| 超碰97人人乐| 91超碰丝袜制服| 青青草综合在线| julia国产在线| 在线看污网站| 搡老女人老熟女91老熟女综合网| 超碰色97| 亚洲男人天堂AV| 亚洲欧美综合| 强奸乱伦 亚洲一区| 国产亚洲精品精AV.| 在线无码视频| 亚洲人妻中文高清| 操婷婷逼| 精品久久久久久亚洲| 亚洲人精品久久久喷水| 日韩影片中文字幕一区二区三区| 色五月69夫妻| 国产成人主播| 日夜尻逼网| 色吊丝 日日骚 清纯唯美| 欧美 亚洲精品首页| 人人操人人色网| 亚洲在线综合| 九九九九九九九九九九九九九九九女| 蜜桃一区二区三区| 综合亚州欧美| 日本不卡一区二区| 久久精品国产99精品亚洲蜜... | 天天天天干| 日韩熟女精品无码专区一区二区| 天美欧美国产| 超碰色美女| 人人操人人色网| 精品少妇人妻av久久免费| 日韩一级片在线看| 人妻激情另类| 九九自拍伦理| 妇女一区二区三区| 性爱综合一区二区| 亚洲操逼视频网站| 偷拍欧美激情| 久湿久久 | 国产精品视频电影| 夜夜 中文视频rt| 91欧美网| av最新免费中文字幕| 五月丁香激情综合网| 粉嫩少妇自慰在线| 人妻少妇精品久久久久久| 国产兽交视频在线播放| 偷看洗澡一二三区美女| 国产夫妻一区二区| 国产午夜福利合集| 欧美日韩啪啪电影| 亚洲AV成人在线| 欧美日韩国产电影| 亚洲欧美碰碰| 欧美强奸乱能| 欧美最婬乱婬爆婬性视频| 国产熟码AV| 国产一区二区在线播放量| 色色亚洲| 熟女露脸激情自拍视频| 极品销魂美女一区二区| www色日本| 综合欧美日韩在线| 又大又大又大又粗爽高潮观看| 欧美三级中文字幕hd| 午夜天堂精品久久| 亚洲日韩美女丝袜美腿人妻视频| 操B在线观看| 东京成人一区| 啊啊啊网站| 9久热| 九九热午夜欧亚国产视频| 久久国产熟女影院| 天美国产精品| 人妻丝袜日本| www激情| 后入式999| 中国国产精品一区视频| 60秒试看最爽10分钟网站| 无码人妻一区二区三区免费九色| 精品v日韩欧美国产| 欧美色图成人网一区二区 | 欧美性爱在线无码| 青青伊人这里只有精品| 乱伦一二三区| 97硬碰| 日韩成人性日韩成人性爱视频在线免费观看 | 狠狠色色| 国产精品3| 激情小说激情视频| 天天插天天操| 欧美精品,四区。五区| 亚洲精品天堂久久A∨51成人漫| 久久av色| 国产精品高清2021在线| 歐美一級亂黃99在綫精品| 精品欧美老熟女一二区| 丝袜熟女2P| 夜色91| 天天射网| TS人妖另类精品视频系列| 97久久资源| 国产熟女精品一区二区| 91精品电影18| 五月丁香黄色网| 亚州色站 日韩电影| 大二网站亚洲| 性性久久| xxx0国产在线播放| 91劲爆| 99热综合| 国产97在线视频| 亭亭丁香激情| 先锋激情∨在线视频播放| 伊人久久亚洲中文字幕不卡| 色噜噜精品一区二区三| 蜜桃臀AV在线| 97精品国产97久久久久久免费| 玖玖资源视频一区二区三区| 欧美黄色大香蕉一区二区| 91女日逼| 999久久久九| 中文字幕乱码人妻二区三区| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 日韩懂色网| 欧美精品99久久久**| 九九九九九九免费视频| 婷色五月| 国产精品不卡一区二区三区av| 98精品国产乱码久久久久久| 岛国黄色大片网站| 99999久久精| 欧美爆操91| 多乙久久久久久| 97超碰超| 中文97国产| 亚洲欧美日韩夜夜| 亚洲成a人v欧美综合天堂下载| 日日干夜夜操视频h| 91高清无码下载| 熟女精品日韩一区二区三区| 欧美亚洲丝袜美女电影| 国产综合永久精品日韩鬼片| 国产熟女无套内射| 精品乱码久久久久| 久久99网站| 黄片免费视频2019| 97国产|免费| 久久久久久久78| 午夜大香蕉| 日韩操逼HD| 亚洲人妻久久| 风月影院男女十八禁| 久久久久无码| 日本精品不卡一二三区| 国产偷人伦激情在线观看| 后入日本1234| 成人日韩中文字幕| 91久久婷婷| 亚洲字幕一区二区| 国产精品久久久 | 一二三区在线| 18禁精品网站在线看| 久久久亚洲| 亚洲色图欧美色图在线播放| 91美乳| 亚洲精品丝袜-不卡成人免费……| 97干综合网| 久久这里只有精品9| 亚洲情色一区三区| 日本九九九九| 国产一区二区三区久久久精品| 欧美操逼录像国产黄色国产| 91天射| 婷婷成人久久久精品| 成人国产精品三级A片| 精品久久久久久中文字幕三区| 搡老女人老91二区| 亚洲九九视频在线观看| 屌妞视频久久久久久久 | 91国产在线精品| 99自拍B亚洲| 大香蕉123| 欧美日韩99| 欧美日本国产日韩激情视频| 欧美五十路熟| 在线视频 亚洲精品| 色九久| 欧美另类丝袜熟女| 福利五区| 午夜AV人气不卡| 日韩一区二区精彩视频| 97精品免费视频网站| 亚洲色图 91| 久久久精品九| 色偷偷2020免费视频播放| 国产精品3| 麻豆黄站| 亚洲天堂久| 国产自偷| 日产精品久久久一区二区| 人妻喷水| 天堂亚洲精品| 日韩大香蕉AV影片| sewuyueav| 欧美日韩资源| 免费试看60秒| 人妻色偷色噜| 人人看人人插| 岛国在线免费视频| 国产性爱在线视频一区二区| 精品一区二区在线针对华人免费观看这里只有精品免费观看 | 性色AV蜜色av色欲av| 国产精品成久久久久午夜午夜| 国产精品不卡av免费在线观看| 欧美一区二区三区不卡高清视频| 91处女在线观看| 成人av性爱电影在线观看|