思考(五十一):登录流程(四)

网关登录流程上的一处并发错误

使用 golang 写网关时,通常每个 socket (玩家) 都是并发处理逻辑的

网关的第一条消息,玩家账号令牌验证 大概率存在并发错误,而程序员往往无法察觉

本人也是昨天刚刚在压力测试中发现的,这里记录一二

常见的 Golang 玩家账号令牌验证 逻辑

(这里假设 gateway 具备会话保持的特性)

常见的逻辑基本如下(伪代码):

func onMsgLogin(...) {
    // 1. 验证 Token
	// 2. 如果有旧账号,踢出旧账号
    // 3. 分配 Lobby 服(或是 游戏服、逻辑服,叫法很多)
    // 4. 返回结果
}

以上代码同一账号同时并发登录存在问题

分析1 - Token 验证

通常会想当然的认为,同账号 2 次登录,数据库 Token 已经变掉了,所以同账号 2 次登录,只会有 1 个验证成功

真实并发时,会存在,数据库 Token 被覆盖前,上个账号已经完成 Token 验证

那么同账号 2 次登录,在 Token 验证 环节都会成功!

即 1 操作仅为验证连接的合法性功能,无法保证 onMsgLogin 函数被重入

分析2 - 踢出旧账号

踢出旧账号,常见的仅为关闭上个 socket 对象,是无法阻止上个账号其 gorouine 中的 onMsgLogin 继续执行完毕的

扫描二维码关注公众号,回复: 8631953 查看本文章

即 2 操作仅为延迟关闭、释放旧账号资源,无法保证 onMsgLogin 函数被重入

分析3 - 分配 Lobby 服

如果想当然的认为, 1 、 2 操作双保险保证下面的逻辑不会被重入,那么分配 Lobby 服,同一账号同时并发登录,会被分配不同的 Lobby 服

因此,这个操作必须具备原子性,保证 2 次并发能是同一个 Lobby 服

分析4 - 可能的后果

同一账号同时 2 次并发登录,可能会被分配不同 Lobby 服

由于其中 1 个账号稍后会马上被踢掉

主要看 Lobby 服上会有哪些业务,才能分析可能的后果

比如,账号登录会在 Lobby 上加载账号数据, Lobby 上账号数据过期 5 分钟会下线

那么可能存在账号数据同时在 2 个 Lobby 上的风险

发布了129 篇原创文章 · 获赞 73 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/u013272009/article/details/89711906