处理玩家的登录,是服务端框架的主要功能之一。分布式系统涉及多个服务,让它们相互配合不产生冲突是一大难点。

1、登录流程

分布式服务端的登录功能要处理好如下两个问题:

  • 问题一:完成角色对象的构建和销毁。如下图所示:

 

         当客户端连接、发起登录时,服务端要创建一个对应角色的程序对象,用以加载角色数据。当客户端掉线时,服务端要保存角色数据,并销毁程序对象。这套框架会为每个客户端创建一个agent服务。

如何解决:需要创建名为agent的服务,它也代表角色对象。

  • 问题二:防止角色重复登录。如下图所示:

        在同一时间,一个角色只能由一个客户端控制,如果用已在线的角色登录,需要先把已登录的客户端踢下线。

如何解决:需要一个记录agent在线状态的服务agentmgr

2、完整登录流程              

        下图展现了登录过程中最复杂的一种情形,即假设客户端B已在线,客户端A要在另一节点登录同一账号。

  • 虚线内的服务位于同个节点;
  • 不同虚线方框的服务可能配置于不同节点;
  • gateway及其对应的loginagent一定位于同一节点上;
  • agentmgr可位于任意节点上。
阶段说明

        客户端A连接服务端某个节点的某个gateway

        (为实现负载均衡,客户端知道所有gateway的地址,并随机选择一个)

        虽然能连接上,但服务端并不知道客户端A要登录哪个角色。客户端A发送消息,消息包含账号密码gateway收到后,随机选择节点内某个login服务,并将消息转发给它

(login服务是无状态的服务,专门用于处理登录校验,一个节点可以开启多个login服务,以分散负载)

        账号,密码通过校验后,login服务会向agentmgr发起登录请求

        agentmgr会记录所有在线玩家的状态(包括登录中、游戏中、登出中),通过向agentmgr发起请求

        agentmgr可以判断账号是否已登录。如果未登录,直接进入阶段⑥,否则先将已登录的客户端踢下线

        agentmgr是个“权威”的服务,角色能不能上线,能不能下线都由它裁决

        agentmgr要求原客户端对应的agent下线(发起kickexit请求),原agent会保存角色数据,然后退出服务。
        agentmgr通知原客户端对应的gateway,让它告诉客户端B“你已被踢下线”。然后设置gateway的状态,取消客户端B与角色101的关联

        agentmgrnodemgr请求创建agent服务

        nodemgr即节点管理器,它可以提供创建服务、节点监控等功能

        创建客户端对应的agent,新agent读取角色数据
        agent创建完毕,agentmgr会记录角色处于“已登录”状态,再通知gateway,让它把新客户端和新agent关联起来
        进入游戏阶段,客户端发送的消息被转发到新agent

 

 3、掉线登出流程

当客户端掉线时,登出流程如下图所示:

 

阶段说明
        客户端A掉线,gateway要取消客户端与agent的关联
        gatewayagentmgr发起下线请求,所有上线下线的请求都必须由agentmgr仲裁
        如果仲裁通过,agentmgr要求代理服务agent下线(发起kicexit请求),agent会保存角色数据,然后退出服务

4、总结

        登录登出过程涉及的步骤较多,越多就越复杂,也就越容易出错。

 问题:

         假设客户端B已在线的情形,但如果在客户端B登录的过程中(比如角色数据尚未全部加载),客户端A请求登录,又该如何处理?会不会造成数据紊乱?

解决:

        这些情况颇为复杂,我们的解决办法是。所有上线下线的请求都要经过agentmgr,由它裁决,只有“已在线”状态的客户端方可被顶替下线,如果处于“登录中”“登出中”agentmgr会告诉新登录的客户端其他玩家正在尝试登录该账号,请稍后再试。 

Logo

鸿蒙生态一站式服务平台。

更多推荐