基于skynet框架的一种游戏服登录模块设计

核心逻辑依赖2个服务模块,中心服务(center)和登录服务(login)

核心设计点

1. 分布式架构:多个中心服务(center)通过取模分配用户,每个中心服务负责一部分用户
2. Token验证:使用Redis存储和验证token
3. 顶号处理:当一个账号在别处登录时,会将前一个登录踢下线
4. 离线处理:玩家下线时,会清理在线状态并通知相关房间
5. 首次登录奖励:玩家第一次登录时,会发放初始货币奖励
6. 登录状态管理:使用记录来防止同时登录

详细步骤

步骤1:客户端发送登录请求(C_LOGIN_GAME)
步骤2:登录服务(login)处理请求,进行初步参数检查
步骤3:调用中心服务(center)进行token验证和登录
步骤4:中心服务(center)处理登录请求,包括顶号处理
步骤5:创建代理服务(agent)并注册到网关(gate)
步骤6:返回登录结果给客户端

系统架构概览

客户端 --> 网关 --> 登录服务 --> 中心服务(验证token、顶号) --> 创建代理服务 --> 注册到网关 --> 返回登录结果

客户端 → Gateway → Login服务 → Center服务 → 数据库/Redis
                   ↓
               Agent服务(玩家实例)

核心登录流程

1. 初步检查:

  • 检查uid和token是否存在,uid是否大于0,token是否非空
  • 检查玩家是否正在登录中,可以使用skynet.uniqueservice定义节点内的唯一服务(例如login_datad,通过login_datad服务进行记录,防止重复登录)

2. 生成一个key(用于后续通信的密钥)
3. 调用中心服务(center)的login方法进行登录:

  • 参数包括节点名、fd、网关地址、key、token等

4. 中心服务(center_login.lua)的dispatch.login方法:

  • 检查是否正在登录(logining_record记录),防止重复登录
  • 根据uid获取用户信息(env.get_user),如果用户不存在则返回失败
  • 从Redis获取最新的token,与传入的token比较,如果不一致则返回失败
  • 如果用户已经登录(user.login_info存在且在线),则踢掉之前的连接(kick_user)
  • 更新用户的登录信息(env.user_login)

5. 如果中心服务返回成功,则继续在登录服务中创建代理服务(agent):

  • 调用libclientagent.login创建agent服务

6. 获取客户端IP
7. 调用中心服务的register方法,将agent信息注册到中心服务:

  • 在中心服务中,记录agent信息,并将用户设置为在线(user_online)
  • 如果是首次登录,发放初始奖励

8. 将agent注册到网关(gate),这样后续的消息就可以直接转发到agent
9. 整理玩家信息,返回给客户端(S_LOGIN_GAME)
10. 清理登录记录,并触发一些后续操作(如每日奖励等)

一些关键点

1. 客户端发起登录请求

  • 检查uid和token是否存在,uid是否大于0,token是否非空
-- login.lua
function forward.C_LOGIN_GAME(fd, msg, source)
    local uid = msg.uid
    local token = msg.token
    ...

关键参数:

  • uid: 用户ID
  • token: 登录令牌

2. Token验证流程

-- center_login.lua
function dispatch.login(uid, data)
    local user_token = libredisproxy.get_token(uid)
    if (not user_token) or user_token ~= token then
        log.error("%d token auth fail %s, %s", uid, token, user_token)
        return false
    end

Token管理:

  • Token存储在Redis中
  • 每次登录重新从Redis获取最新token
  • Token不匹配立即拒绝登录

3. 顶号处理机制

踢号流程:

  1. 发送踢下线协议给客户端
  2. 调用gateway的kick接口断开连接
  3. 清理在线状态记录

4. 用户数据加载

数据分层:

  • Redis: Token等临时数据
  • MongoDB: 玩家基础数据
  • 内存缓存: 活跃玩家数据

5. 分布式节点分配

负载均衡:

  • 基于UID取模分配到不同Center节点
  • 每个Center服务管理一部分用户

6. 首次登录处理

首次登录特征:

  • 检查logingametime字段
  • 发放初始货币奖励
  • 初始化账户数据

7. 在线状态管理

在线用户池:

  • 使用对象池管理在线用户记录
  • 记录agent服务地址和节点信息
  • 支持快速查找在线用户

完整登录时序图

在这里插入图片描述

常规登录流程:

  1. 客户端发送C_LOGIN_GAME消息到网关,网关转发到登录服务
  2. 登录服务检查参数,生成key,并调用中心服务的login方法
  3. 中心服务检查token,如果token无效则返回错误
  4. 如果token有效,检查是否已经在线,如果在线则踢下线
  5. 更新用户登录信息,返回成功
  6. 登录服务创建代理服务(agent)
  7. 登录服务调用中心服务的register方法,注册agent信息,中心服务将用户状态设置为在线
  8. 登录服务将agent注册到网关,使得后续消息直接路由到agent
  9. 登录服务返回S_LOGIN_GAME消息给客户端,登录成功
  10. 客户端与代理服务开始通信

顶号流程:
11. 用户A在设备1登录,中心服务记录其登录信息(包括agent、fd等)
12. 用户A在设备2登录,中心服务发现已经在线,则调用kick_user踢掉设备1
13. kick_user会向设备1发送S_KICK_LOGOUT消息,并关闭设备1的连接
14. 设备1收到踢下线消息,断开连接
15. 设备2完成登录

离线流程:
16. 用户正常下线:客户端发送 logout 消息,经过agent调用中心服务的logout,清理在线状态
17. 用户异常断开:网关检测到连接断开,会调用agent的kick方法,agent再调用中心服务的logout

设计优势

1. 安全设计

  • Token验证: 每次登录重新验证
  • 防重复登录: 分布式锁机制
  • 顶号保护: 强制踢出前一个会话

2. 性能优化

  • 数据缓存: 活跃用户内存缓存
  • 连接池: 在线用户对象池
  • 分布式: 用户按节点分散

3. 状态一致性

  • 登录状态原子操作
  • 失败时资源清理
  • 离线时状态同步
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值