如何同步API中的slice与map以避免用户会话锁定
问题场景与解决方案
问题概述
我开发了一个供其他程序调用的API,核心流程如下:
- 用户认证通过后,API返回一个专属ID,用户需使用该ID连接WebSocket
- 发送ID时将其加入slice,确保同一凭证用户无法同时拥有两个会话
- 用户成功连接WebSocket后,将该ID存入存储连接与ID对应关系的map中
- 连接关闭时,从slice移除ID并删除map中对应的键值对
但存在一个异常场景:如果认证请求完成,但WebSocket连接未建立且客户端直接关闭,ID会一直留存于slice中,导致用户被锁定无法重新登录,需要解决slice与map的同步问题。
最终解决方案
我改用单个map统一存储会话信息,并在路由初始化时启动一个定时清理协程,定期移除未建立WebSocket连接的过期ID:
go func() { staleCheckInterval := time.Second * 10 ticker := time.NewTicker(staleCheckInterval) for { select { case <-ticker.C: log.Println("检查过期ID") staleIds := []string{} for k, v := range handler.WsClients { // 如果ID生成超过10秒且未关联WebSocket连接,判定为异常状态 if v.Ts < int(time.Now().UnixMilli())-10000 && v.WsConn == nil { staleIds = append(staleIds, k) } } for _, id := range staleIds { delete(handler.WsClients, id) log.Println("移除ID:", id) } } } }()
方案说明
- 用单个map替代slice+map的组合,统一存储会话ID、关联的WebSocket连接、ID生成时间戳(
Ts)三类信息 - 启动定时协程,每10秒扫描一次map:
- 筛选出"生成超过10秒且未建立WebSocket连接"的无效ID
- 批量删除这些过期ID,避免用户因异常场景被锁定
内容的提问来源于stack exchange,提问作者Fergus Johnson
相关产品推荐
相关产品推荐

