mangos源碼分析
轉自:http://eric-weitm.iteye.com/blog/1457395
一、線程分佈:
1、主線程 main---- Master::Run() ,主要功能:初始化world、創建子線程、回收資源
2、WorldRunnable -------GS主線程
3、CliRunnable -----後臺調試線程
4、RARunnable -------事件處理和分發線程
5、MaNGOSsoapRunnable---協議
6、FreezeDetectorRunnable
7、線程池 Master::Run----WorldSocketMgr::StartNetwork---WorldSocketMgr::StartReactiveIO ---ReactorRunnable
二、事件分發和處理
WorldRunnable::run---World:update----World:UpdateSessions---WorldSession::Update(一個socket內所有事件)---各種各樣的handler
基本框架:ACE的Reactor機制(ACE_TP_Reactor)
三、WorldRunnable 主要功能
WorldRunnable ----World 定時器任務+網絡事件(session中的)+異步IO回調+任務系統調度+cli
整個game server的併發模型
一 概述
game server至少要提供如下幾類的功能 :
1、響應客戶端請求-------WorldRunnable
2、後臺命令 -------CliRunnable
3、分佈式架構(RMI等) -------MaNGOSsoapRunnable
可以看到針對這幾類功能,mangos都給予了支持。
二、WorldRunnable響應客戶端請求的併發實現
game server會提供很多服務,如組隊、加好友、交易、走路、戰鬥……,從宏觀上講這些服務是同時對外提供的,另外IO操作是費時的,
必須將IO與邏輯處理分開,這樣的話一個基本的實現是這樣的:
1、開啓IO線程,所有費時的操作交由此處處理 WorldDatabase.ThreadStart();
2、利用協程來實現各個子系統,或者利用心跳來實現各個子系統的調度(不能開很多線程,線程代價太高)
三、Mangos的心跳實現
void World::Update(uint32 diff)
基本上包括幾類:
1、檢查定時器---------------時間
2、刷任務
3、維護session---------------------人物
4、全局環境更新(map、battleGround)--------地點
5、處理服務器事件------------------事件
6、其他(數據同步、後臺調試、IO回調……)
四、game server運行的機制
1、定時器觸發
2、事件觸發(鬆耦合)
五、典型的一種service的實現方式
1、IO協程將cammand入隊
2、worker協程 依次fetch、execute
核心數據結構是線程安全的隊列
GS生命期內主要的事件---------狀態機的狀態轉換主要是基於事件
一 game server狀態機
startup
LOAD
Compile
init
running
shutdown
二 角色狀態機
login
enter_world
enter_map
leave_map
leave_world
relogin
logout
三 角色commands的命令種類
login、auction, buy, chat, express, move, task, select_menu_item, stall……
四 server端service的組織
1、結構化(純c實現) clone, feature、cmds(命令入口filter)、daemons(抽象的功能模塊)
2、OO 各個層次的router,XXHandler, 一般在session中的總入口是player
session管理
一、world核心數據結構:環境+session
SessionMap m_sessions;
Queue m_QueuedSessions;
typedef UNORDERED_MAP<uint32, Weather*> WeatherMap;
WeatherMap m_weathers;
二、WorldSession 核心數據結構 玩家+信道+消息隊列
Player *_player;
WorldSocket *m_Socket;
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue; // 每個session有一個消息隊列
整個session就是不停的fetch,處理msg的過程
OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()]; // 利用一次映射找到handler
handle_input_payload----int WorldSocket::ProcessIncoming (WorldPacket* new_pct)--------void WorldSession::QueuePacket(WorldPacket* new_packet)
三、player核心數據結構 map、權限、社會關係、管理員?拍賣?談話 存儲 包裹 物品……
概述:所有command緩存在socket的隊列中,各個子系統的總入口是player
服務端每一幀的邏輯:
1、從OS處取出到達的事件到本進程(所有的事件已經緩存在socket隊列中)
2、依次調度各個子系統或子子系統
對於node.js而言,線程調度、事件緩存、回調機制已經都實現了,程序員只要實現具體的邏輯和定時器(子系統)就可以了
game server內嵌的http服務
如何使gs響應http的請求? 基本思路 實現簡單的http server框架、具體遊戲邏輯轉發給內部handler來處理
一 初始化
開啓監聽線程(協程)檢查端口、設置緩衝區大小
每一個socket連過來時 1、開新協程處理(有調度開銷) 2、放入共享隊列中,由worker線程池共同維護(有數據同步的問題)
設置每個請求URI對應的回調接口
二 服務期
1、一個socket數據到來後,開新線程,解析http數據,分析出請求的uri、回調、關閉socket、關閉線程(因爲http是無連接的)
2、一個socket到來時,其被放入某個thread內部的sockets數組中,
當此worker thread池被調度到之後,依次處理每個socket的數據就可以了(唯一區別是多個sockets由幾個線程維護)