websocket與http的區(qū)別?
Http:請求與響應(yīng)的模式,屬于“半雙工”,服務(wù)端只能接收客戶端的請求做出響應(yīng),無法主動推送數(shù)據(jù)。
websocket:服務(wù)端與客戶端可以隨時(shí)給對方發(fā)送信息,屬于“全雙工”,能夠?qū)崿F(xiàn)雙方實(shí)時(shí)的推送數(shù)據(jù)。
websocket的應(yīng)用場景?
實(shí)時(shí)推送數(shù)據(jù)(客戶端->服務(wù)端,服務(wù)端->客戶端)
如果沒有websocket,http可以通過長輪詢的方式,不停地發(fā)送請求去詢問服務(wù)端是否有數(shù)據(jù)可以響應(yīng);但頻繁的請求,會浪費(fèi)雙方的資源(CPU、帶寬等)
項(xiàng)目實(shí)踐:
- IM實(shí)時(shí)通信與多端同步
- 服務(wù)端的定制化推送服務(wù)
websocket通信方式
- 握手,利用 HTTP 協(xié)議實(shí)現(xiàn)連接握手,請求中進(jìn)行“協(xié)議升級”,握手過程中,為了防止誤連接進(jìn)行一個(gè)Sec-WebSocket-Key的認(rèn)證機(jī)制
- 通信,握手成功后,即可雙工通信
- 心跳,即PING PONG,websocket中最好有心跳來維持服務(wù)端與客戶端的長連接通信,避免被網(wǎng)關(guān)等誤以為無效連接;可以通過websocket本身協(xié)議配合,或者直接客戶端/服務(wù)端發(fā)起心跳來維持
- 關(guān)閉,客戶端或服務(wù)端發(fā)送關(guān)閉的信號,亦或者是一些意外導(dǎo)致強(qiáng)制關(guān)閉
websocket協(xié)議結(jié)構(gòu)

websocket協(xié)議
- FIN:消息結(jié)束的標(biāo)志位;
- RSV:預(yù)留字段,為0;
- opcode:操作碼(類型),1表示幀內(nèi)容是純文本,2表示幀內(nèi)容是二進(jìn)制數(shù)據(jù),8表示關(guān)閉連接,9表示連接?;畹腜ING ,10表示連接?;畹腜ONG;
- MASK:是否使用異或來進(jìn)行掩碼;客戶端發(fā)送數(shù)據(jù)必須使用掩碼,而服務(wù)器發(fā)送則必須不使用掩碼
- Payload len:幀內(nèi)容的長度
- Extended payload length:擴(kuò)展字段
- Masking-key:如果MASK需要掩碼,則為4 個(gè)字節(jié)的隨機(jī)數(shù)
- Payload Data:幀內(nèi)容
分布式下IM多端同步的實(shí)現(xiàn)方案

2022-12-7-im多端同步-V2.png
- websocket多端與后端服務(wù)建立連接
- redis存儲會話信息與會話狀態(tài)
- websocket發(fā)起IM通信
- server接收IM消息,投遞到mq
- mq進(jìn)行廣播,多server訂閱
- 在redis查找存活狀態(tài)的業(yè)務(wù)會話,server除發(fā)起方的websocket,找到當(dāng)前server有效的websocket進(jìn)行數(shù)據(jù)的同步
TIP
- 如果沒有心跳,通過控制臺強(qiáng)制殺客戶端進(jìn)程,或者是斷網(wǎng),會導(dǎo)致服務(wù)端沒辦法知道客戶端已“異?!标P(guān)閉;所以需要有“心跳”來維持這個(gè)狀態(tài),服務(wù)端主動或被動的維護(hù)websocket session的狀態(tài)(調(diào)度清除無用session或心跳回復(fù)后的懶清除)
- 關(guān)于多端同步,websocket的通信是端對端的,對于服務(wù)端來說,服務(wù)一般是集群的,而不是單機(jī)的方式,而websocket的session無法序列化,無法通過分布式的組件來存儲并序列化session,如果需要考慮多端消息同步,只能通過廣播的方式,通知給每一臺服務(wù)端,由各自的服務(wù)端發(fā)起websocket請求。
- 關(guān)于websocket最大的長度:沒什么受限,但是用的組件(例如tomcat或者springboot可能會有限制長度)
- 關(guān)于wss:類似https,多個(gè)s即多個(gè)證書,證書對通信進(jìn)行加密,避免通信過程中直接裸露在網(wǎng)絡(luò)上,可在nginx上配置。
- 多端同步過程中,rocketmq是沒辦法同時(shí)使用順序方式+廣播模式;原因是廣播是不加鎖的,順序方式雖然是同一個(gè)queue,但如果采用順序方式+分布式模式,那么多個(gè)消費(fèi)者線程會同時(shí)處理同個(gè)隊(duì)列,也會導(dǎo)致多端同步的數(shù)據(jù)亂序;
解決方案是:分布式模式只限制一個(gè)消費(fèi)者線程(保證消費(fèi)數(shù)據(jù)也能夠是順序的),只要保證某個(gè)會話是順序的的,那么可以使用線程池并進(jìn)行線程復(fù)用與分片,多線程消費(fèi)mq訂閱的消息。