Home
Posts
Categories
Series
Tags
About
WebSocket
postedOn: 2026-8-29   updatedOn: 2026-8-29   includedIn: 程式
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

  1. 檢查本地cache是否有資料

  2. 檢查redis是否有資料

Http

位置: other api

  1. 檢查redis是否有資料

  2. 做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是否一致,不一致就不刪除,這樣就不可能刪到不同連線的資料