服务器比较

1.两个框架
mobile legends
{
        微服务架构:各系统耦合性低,rpc
        AccountServer        DirServer
                    LoginServer---c(账号认证,角色信息,区服信息)
                        |
                        |
        ConnServer    ConnServer ConnServer---c
        GameServer    GameServer GameServer---SharedMemory---MySql

        RankServer     FriendServer
        TeamServer    MatchServer --- BattleServer BattleServer
        PingServer    BroadServer --- BattleServer BattleServer
                    
        epoll线程(Server)(1-N)    ServiceHandleThread(1-N)
        epoll线程(Client)(1-N)    AsyncRspThread(1-N)
        
        附上一个配置,更好理解
         <mfw>
             <application>
                 setdivision = moba.zone.2006
                 <client>
                     locator                     = mfw.mfwregistry.QueryObj@tcp -h 192.168.40.220 -p 2000//注册服务器地址
                     refresh-endpoint-interval   = 60000
                     sync-invoke-timeout         = 3000
                     async-invoke-timeout        = 5000
                     connect-timeout             = 1000
                     asyncthread                 = 3
                 </client>
         
                 <server>
                     app      = MOBA
                     server   = GameServer
                     logpath  = ~/log
                     loglevel = DEBUG
                     framework-loglevel = INFO
                     log      = mfw.mfwlog.LogObj
                     loop-interval = 50
                     admin   = tcp -h 127.0.0.1 -p 0 -t 10000
                     agent-report = mfw.mfwagent.AgentReportObj@tcp -h 127.0.0.1 -p 2002 -t 3600000
         
                     <Service_1>
                         service    = MOBA.GameServer.GameServiceObj
                         endpoint   = tcp -h 192.168.40.210 -p 2024 -t 600000
                         protocol   = mfw
                         threads    = 1
                         maxconns   = 1024
                         queuecap   = 10240
                         queuetimeout = 5000
                     </Service_1>
                 </server>
             </application>
        </mfw>
}

300英雄
{
            整体性架构:耦合性高
            ShareMemProc:只申请共享内存
            LocalSaveServer读取共享内存发送到--->ManagerServer
            Client
             |
             |
            GateServer(多个)--->AuServer(账号验证)
             |
             |
             |
   GameDB---ManagerServer--->(GameAIServer,NameServer,CenterServer---GameDB)
             |
             |
             |
            GameServer(多个)---ShareMemProc----LocalSaveServer
    
    
    IOCP与epoll最大不同:IOCP时间通知时,已经做好了I/O,而epoll,还得自己去读写。
    
    CIOCPSessionIdleRunThread::StartIdleRunThread  CIOCPSessionIdleRunThread::IOCPIdleRunThread CManagerServerConnector 1个
    CIOCPSessionWorkThread::StartWorkThread      CIOCPSessionWorkThread::IOCPWorkThread  CManagerServerConnector 10个
    GateListener            CTcpServer::RunByNewThread    1个
    CClientBattleListener    CTcpServer::RunByNewThread    1个
    CThreadServer::LogicProcessThreadFunc  GameServer逻辑线程
    CThreadServer::TimeoutDumpThreadFunc   TimeOutDump线程
    Log线程若干个
    main线程
}


2.两个登录流程
mobile legends
{
    DirServer
    增加,修改-后台网页操作

    维护所有分区的当前信息        
    创建,修改,上报分区信息
    分区:状态,版本号,注册量等

    一.loginserver    
        定时从dir同步所有区服的信息
        1.CmdId_Login_Auth_CS->LoginServer
                    1_1:ip获得国家,然后根据渠道看是否禁止登陆
                    1_2:到accountserver获取账号信息,创建账号信息
                    1_3:推荐分区(最近登录的一个分区)
        2.CmdId_Login_GetZone_CS->LoginServer获取一个账号的相关角色信息(内网没有调用)
                    所有区服和角色的基本信息
        3.Cmd_Login_CheckUpgrade_CS
                    各种地址,包括connectserver的地址,cdn头像上传等
        4.CmdId_Login_GetBulletin_CS
                    获得游戏公告
        5.Cmd_Login_UpdateDeviceToken_CS(内网没有调用,可能在某些情况下调用)
                    上报devicetoken
        6.Cmd_Login_GetRegion_CS(内网没有调用)
                    各个大区的信息
                
    二.与connserver连接
        CmdId_Net_Connect_CS:连接connserer
        CmdId_Net_LogReport_CS:上报客户端日志
        CmdId_Role_Init_CS:获取角色详细信息
        CmdId_Net_Idle_CS:维护客户端连接心跳
        CmdId_Account_GetAccount_CS:获取账号相关信息

    三.与GameServer连接
        CmdId_Net_Connect_CS
        CmdId_Net_SetSkeyExpireTime_CS:ConnServer 通知 GameServer 过期时间
        CmdId_Role_Init_CS
        CmdId_Account_GetAccount_CS
        CmdId_Net_ServerTime_CS
    }

300英雄
{
    帐号验证
        gate -> client            MsgLoginDataWrapper(Sg2cSecretKey)
        client -> gate            MsgLoginDataWrapper(Sc2gReqClientLogin)                //登陆消息

        gate -> audbgate        Sg2aReqClientLogin                                    //验证服务器(通过登陆账号密码返回具体玩家账号信息)
        audbgate -> gate(Sa2gAckClientLogin) -> client(Sg2cAckClientLogin)            //返回具体玩家账号信息

        gate -> manager     MsgReqLoginCheck
        manager -> gate     MsgAckLoginCheck

        gate -> manager            DBMsgReqGetAllRoles                                    //获取所有角色信息
        manager -> db                Sm2dReqAllRoles
        db -> manager                Sd2mAckAllRoles
        manager -> gate            MsgResGetAllRoles
        gate -> client            MsgResGetAllRoles        1287  如果m_btRoleNum数量为0则进入创建流程,如果大于0则进入选角色登入流程
        
    登入流程
        client -> gate            MsgEnterWorld                    //获取角色信息
        gate -> manager            DBMsgReqGetOneRole
        manager -> db                Sm2dReqGetOneRole
        db -> manager                Sd2mAckGetOneRole
        
    1、Client-连接->GateServer  GateServer保存会话OnNewClientConnected
    2、Client-发送MSG_LOGINDATAWRAPPER->GateServer   登陆消息
    3、GateServer-登陆消息->AuAgent   验证服务器(通过登陆账号密码返回具体玩家账号信息)
    4、AuAgent-返回具体玩家账号信息->GateServer   GetAU().Run()-ProcessAUAgentProtocol-通知客户端验证-OnAckLogin-更新1会话
    5、ManagerServer-MSG_S2C_RESPONSEGETALLROLES->GateServer   ManagerServer发送人物信息给玩家,早期可能是GameServer发送的
    6、Client-MSG_ENTERWORLD->GateServer-MSG_GMD_REQUESTGETONEROLE->ManagerServer   获取角色信息
    7、ManagerServer-em2dReqGetOneRole->DB(CAccountManager) 向账号管理请求角色信息(DBServerConnector)
    8、DB->ed2mAckGetOneRole->ManagerServer DB返回数据至ManagerServer
    9、ManagerServer->MSG_DMG_RESPONSEGETONEROLE->GameServer ManagerServer将DB数据组装发给GameServer,GameServer更新玩家信息
    10、GameServer-MSG_ACKENTERWORLD->GateServer->Client 进入世界 清除临时登陆信息m_TempSessions、m_LoginSessions 建立以dwPlayerCharacterID为索引的会话m_GameChars
}

3.两个战斗流程
mobile legends
{
1.创建房间
CmdId_Room_Create_CS
    1_1到pingserver获取ping返回(格式:groupid:ping值)
    遍历这些battlegroup,检测battlegroup的版本(t_battle_group),在所有battle中找(t_battle_status)这个版本号和状态时正常的,确定本次匹配的matchid
    game上有一个battlegroup->matchid的列表,是从数据库中取得
    取第一个battlegroup的matchid,然后过滤后面的battlegroup的matchid。获得一个battlegroup的列表。
CmdId_Room_Enter_CS(单人匹配不会调用)
    进入房间,根据模式,判断各种限制条件(段位,版本号等)
CmdId_Battle_StartMatch_CS
    从roomserver获取房间里面的玩家信息,开始匹配,根据玩家身上存储的matchid选择在哪个matchid进行匹配,会将房间里面的所有玩家信息带到match上
    发送CmdId_Match_StartMatch MatchServiceMsg到match上,battlegroup信息也带到match上
    根据带到match上的battlegroupu列表,筛选出可用的battlegroup列表(版本号,在线人数),然后同时在这些battlegroup里面匹配,扔到几人匹配的list里面
    loop每一帧从list匹配玩家,匹配成功后找到这个battlegroup里面的battle,加入到这个battle上面比赛,在一个battlegroup里面匹配成功了,则删除其他battlegroup里面匹配的该玩家
    
    1.分battlegroup,到battlegroup中匹配
    2.每个battlegroup分模式,相同模式一起匹配
    3.分人数(1,2,3,4,5) 不同人数在不同的list中,计算单人或者组队的匹配值,list按照匹配值排序从小到大
    4. ProcessList5();    判断两两之间能不能匹配,遍历列表迭代器和前一个迭代器的队伍能不能匹配
       ProcessList4();  (4,1)->5
       ProcessList3();    (3,2)->5 (3,1)->4
       ProcessList2();    (2,1)->3
       ProcessList1();    遍历单人列表,迭代器向前向后找到5个人队列中
       ProcessList0();  已匹配好的删除掉
    5.找battle 遍历所有battle,然后找这个匹配的battlegroupid(m_uiSvrID/1000),找出人最少的,到相应的battle上创建战斗,battle会上报数据到match上
    6.battle上报信息到match上,gameserver上面会从battlegroupid->match的列表
       
       
    再BattleServer上创建战斗
    HandleConn::dispatchOneCommandByMain
    使用了一个状态模式

    CmdId_Battle_Oper_CS 
        Battle::DispatchBattleOper,玩家操作m_vecBattleOperData.push_back(stBattleOper);
    CmdId_Battle_Result_CS
        客户端上报战报
    CmdId_Battle_Hash_CS
        客户端上报MD5
        pPlayer->m_strMD5 = stReq.sMd5

    66ms一帧
    1.Battle::LogicUpdate,将66ms内玩家的操作广播给10个玩家
    2.检测MD5,取大多数为正确的MD5,则其他人不正确
    3.比对战报的MD5,拿大多数人的结果作为服务器战报
    
} 

300英雄
{
    ManagerServer->GameAIServer
    CELO_Super_Queue-CElo_Base_Queue-m_listNode:不同类型的战斗排队列表
    
    匹配成功
    GameAIServer->ManagerServer
    ManagerServer(m_quAthReady保存已就位的队伍信息)->GameServer
    CAthleticsManager::SendReadyTeamToGS:找人数最少的game
    
    GameServer开始创建副本,切线(比如从1线切到3线)
    1.玩家从1线下线,存储玩家的信息,并在ManagerServer上设置玩家处于切线状态
    2.玩家重新登录DBMsgReqGetOneRole,然后登录到玩家要切的那条线上EnterWorld
    3.客户端直连GameServer开始战斗
    4.进入到玩家的副本中,里面有个状态机控制玩家当前进入到了哪个阶段
    5.结束之后玩家再次走切线流程,切换到原来的线中
    
    
    AI:ai玩家注册一个100ms的定时器,给ai分配了总共18个任务,
        1.根据任务的不同执行不同的ai脚本
        2.ai有不同的状态,根据状态的不同调用不同状态的update
    
    技能:
        1.考虑施法距离,如果距离不够,移动到目标点
        2.技能开始释放分阶段
            前摇  
            攻击(吟唱,引导),结算:结算自己,结算目标(前,时,后)
            后摇
            
            这里面很多都是通过状态实现,大部分是策划脚本加的状态,玩家身上有个状态列表,然后定时器驱动这些状态执行动作
    怪物AI:
        空闲(IDEL)
            |
            |(受到攻击,从附近找一个最近的可攻击,保持攻击2s,加入到攻击列表)
            |
        战斗状态
            目标死亡:丢失目标LostTarget(从攻击列表中找最近)
            |
            |
            (能否保持攻击)
            否:丢失目标 LostTarget(从攻击列表中找最近)
            是 {    1. 2s的保持攻击结束,从最近攻击的列表中寻找最近的继续攻击
                    2.继续攻击之前的目标
               }
        状态机实现
    视野:
        1.视野组
        2.附近的玩家
        3.九宫格通知
        
    定时器实现
        1.高等级定时器
            数量少,时间短,直接是一个vector,遍历执行,这些定时器和其他的分开单独执行
        2.
            100ms      0~20 20~40 20~40 ... 180~200
            100ms_1    200~300 300~400 ...    1100~1200
            long    1200~2200            10200~11200
            >11200
            新的根据定时器的执行时间插入到对应的队列中
            老的也会遍历每个slot中的,计算时间放到上一层对应的slot中,最终到时间了放入m_waitExecute待执行列表中
            接下来直接执行m_waitExecute中的定时器。
}

4.玩家数据管理
mobile legends
{
    共享内存mmap
    CMemKV m_mBlob; ---管理共享内存
    玩家上线从m_mBlob反序列化出该玩家信息 到unordered_map中
        
   1.初始化共享内存
   2.从db中获取所有玩家数据,放入共享内存中
   3.owner.setChanged():同步到共享内存中
   4.BlobManager::loop 从m_mBlob中取出脏的blob放入异步队列中,这步有个令牌桶限流
   5.存储DB线程从异步队列中取出更新到数据库
  
  GetRoleByUid:首先从内存中获取,获取不到从m_mBlob反序列化出来
  
  实在看不懂MEMKV也没有任何资料介绍
}
 
300英雄
{
    hash_map:玩家id->到共享内存块的映射 
    玩家上线:
    1.如果已经在共享内存,直接拿过来用
    2.从共享内存中找到一块空闲的给该玩家,
    3.注册一个定时器5分钟,同步一次数据到ShareMemory,也可以自己手动同步
    LocalSaveServer 将共享内存里面的脏数据数据发送到Manager再到DBServer
}
 

 

posted @ 2020-10-18 23:21  zzyoucan  阅读(246)  评论(0编辑  收藏  举报