前言
服务端登录需要考虑登录的账号验证,和分布式集群引入的多点登录问题,并且由于存在登录状态而引发的断线重连,顶号等问题。通常这些问题可以归为一类,都是围绕登录流程所展开的。
一.账号验证
账号验证分为两种:1.通过第三方平台验证(google, appleid...) 2.账号密码验证 3.将以上两种方式结合
a.通过第三方平台验证 通过第三方平台验证,需要在客户端接入第三方平台的验证接口。通过上报gmail账号等信息,从第三方平台获取验证凭证,然后将凭证传给服务端。服务端通过调用第三方平台的接口验证凭证的有效性,如果验证通过,则返回验证成功,否则返回验证失败。
b.账号密码本地验证 客户端将账号密码传给服务端,服务端通过数据库查询账号密码是否正确,如果正确则返回验证成功,并生成用于验证Game Server的验证token,将token存储于数据库中(例如redis), 用于客户端之后通过sessionid进行登录时候的验证。如果正好密码错误返回登录失败,不存在则新建角色。
3.以上的两种方式结合 第三种方式好处是可以利用服务器自己生成的token进行验证,并且能利用服务器token进行断线等操作
2.登录流程
账号验证通过之后,紧接着进行的是登录流程,不同的架构设计,登录流程也会有所不同。需要注意的是登录状态的保存,和分布式锁。 - 登录状态: 其他服务查询当前登录状态,例如好友,邮件等功能,以及断线重连,顶号等问题 - 分布式锁: 防止多点登录,顶号等问题。一般采用redis的分布式锁的方式
1.获取玩家所拥有的角色信息的流程图:
流程图的步骤说明: 1. 客户端携带第三方平台返回的token,发送给Gate 2. Gate将token转发给Session 3. Session在开始登录时,设置分布式锁,防止多点登录 4. 验证token的合法性 (token由验证服Auth写入) 5. Session获取玩家角色简易列表 (openid -> roles的映射) 6. Session返回角色列表和验证结果 7. Gate转发给客户端角色列表
2.选定角色登录流程图:
流程图的步骤说明: 1. 客户端角色选择后,发送给Gate 2. Gate将角色选择信息转发给Session 3. Session从redis查看玩家是否已在线 1. 在线:获取玩家world的appid 2. 不在线:返回world的appid = 0 4. Session验证角色是否存在与有效 5. Session返回角色验证结果与world的appid 6. Gate通过world的appid转发给对应的world,若appid==0,Gate随机选择world转发 7. World判断玩家是否已存在,如果存在走顶号,不存在走正常登录 8. World从Mysql中获取玩家存档信息 9. World向Gate返回登录结果 10. World通知Session登录完成,可以释放分布式登录锁 11. Gate向客户端通知登录结果
3.登录状态机
登录过程中伴随各个进程上玩家状态的变化,尤其是Gate和Session上状态需要维护正确,以保证登录流程的正确性。 - 确保每种状态开始时检查是否为上一种状态,因为登录流程是线性的 - 分析登录流程的消息如果不可达,发送了两条等会不会出问题 - 随机上下线确保登录,顶号,断线重连的正确性