WebSocket
wordsCount: 929
readingTime: 2 mins
viewers:
緣由
Ws server接觸一年後,之前剛好經手一個功能,讓我對ws和http的資源的建立和釋放有更深的理解
[建立資源動作]
WebSocket
位置: OnOpen
1.去打相關驗證登入api
2.redis存資料,不設ttl
3.本地cache存ws連線 (使用者的ws連線在很多業務狀況下,都可能非同步的被使用&ws連線無法存到db)
Http
位置: Login api
1.在redis用ttl方式存資料
2.為了無狀態,通常不存local cache
[後續溝通使用資源] (是否登入判斷)
WebSocket
位置: OnMsg
-
檢查本地cache是否有資料
-
檢查redis是否有資料
Http
位置: other api
-
檢查redis是否有資料
-
做redis ttl續約 (延長存活時間)=>也可能是獨立api
[釋放資源動作]
WebSocket
位置: logout event & OnClose
1.去打相關驗證登出api
2.redis刪資料 或者 設ttl
3.清除本地cache
Http
位置: Logout api or Redis TTL過期
1.收到登出後,去redis刪資料
2.一直沒有登出,就等redis ttl過期自動刪除資料
討論web socket的釋放資源(實務上問題)
正常流程應該是收到logout event做第一階段的資源釋放,斷線後OnClose做第二階段資源釋放
但有時候前端直接斷線,根本沒有收到logout event,就只做OnClose做第二階段資源釋放,就會出問題
解決方案:冪等清理 (資源釋放只做一次)
正常情況logout event就一次全部釋放完成,斷線後OnClose不做事,如果前端直接斷線,就讓OnClose也做全部釋放
為何這很重要?
我在一個運行3年的server,發現原本的設計是做重複釋放,雖然大部分情況下,東西刪除兩次不會造成問題,
但是當使用者,斷線後快速重連,第一個連線的OnClose還沒做完資源清理,第二個連線就已經建立資源,
導致第一個連線的OnClose刪掉了第二個連線的資源
=> 自己被自己踢出去(資源的Race Condition)
更好解決方案:資源應有Session/Connection 身份識別 (類似樂觀鎖)
=>問題不在順序,而在每個連線用到的Key都有唯一性,讓舊連線去慢慢清理
如果是Hash,使用者Id當key,裡面的value其中一個要放連線Session,刪除時,
檢查Session是否一致,不一致就不刪除,這樣就不可能刪到不同連線的資料
Table of Contents
Related Posts
設計模式-工廠模式
Factory -工廠模式 分類 建立模式-Creational Patterns 主要角色 Product (產品介面)、Concrete Product (具體產品
2026-4-12
設計模式-策略模式
Strategy-策略模式 分類 行為模式-Behavioral Patterns 主要角色 Strategy (策略介面)、Concret
2026-4-12
MySQL和PostgreSQL交易快照比較
此篇討論Mysql和PostgreSQL的快照機制 MVCC (Multi-Version Concurrency Control) 多版本併發控制,核心在於使用版本來代替鎖來
2026-4-12
Mysql 的 Repeatable Read & 幻讀
此篇討論Mysql RR下,預設解決了哪些幻讀,哪些沒解決?如何處理剩下的幻讀問題 定義 快照讀 : select 當前讀
2026-4-12
交易隔離等級
What we talk this ? 在不同的商業模式下,注重的核心不同,有些要速度,可接受不準確,有些要資料精準,可接受慢一點
2026-4-12
Sponsor
Wechat
Alipay