Files
hjha-server/GlobalSever/GlobalManager/GlobalManager.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
2026-07-07 12:02:15 +08:00

846 lines
25 KiB
C#

/*
* 由SharpDevelop创建。
* 用户: Administrator
* 日期: 2018-09-13
* 时间: 17:14
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using GameData;
using MrWu.Debug;
using MrWu.RabbitMQ;
using Server.Data.Module;
using Server.DB.Redis;
using Server.DB.Sql;
using Server.MQ;
using Server.Pack;
using Server.Config;
using Server.Core;
using Server.Net;
namespace Server
{
/// <summary>
/// 全局管理
/// </summary>
public abstract partial class GlobalManager : ITimerProcessor, IServer
{
/// <summary>
/// 是否需要重新加载配置
/// </summary>
public bool IsReloadTable;
/// <summary>
/// 服务器单元工厂
/// </summary>
public static ServerUtilFactory Factory;
private static GlobalManager mInstance;
/// <summary>
/// 每个服务器只能管理一个服务,单例模式
/// </summary>
public static GlobalManager instance
{
get
{
if (mInstance == null)
mInstance = Factory.GetGlobalManager();
return mInstance;
}
}
#region
/// <summary>
/// 是否自杀
/// </summary>
public bool isKill { get; private set; }
/// <summary>
/// 是否可以开战,关闭服务器前先禁止,然后再关闭服务器
/// </summary>
public bool IsCanWar = true;
/// <summary>
/// 客户端要得到的配置
/// </summary>
public ConfigHead ClientConfig;
/// <summary>
/// 服务器信息
/// </summary>
protected ServerInfo m_serverinfo;
/// <summary>
/// 服务器信息
/// </summary>
public virtual ServerInfo serverinfo
{
get
{
if (m_serverinfo == null)
m_serverinfo = new ServerInfo();
return m_serverinfo;
}
}
#endregion
/// <summary>
/// 获取配置头
/// </summary>
/// <returns></returns>
protected virtual ConfigHead GetConfigHead()
{
ConfigHead cfh = new ConfigHead();
cfh.style = 1;
cfh.id = ServerConfigManager.Instance.NodeId;
cfh.num = ServerConfigManager.Instance.NodeNum;
cfh.maxSVer = ServerConfigManager.Instance.MaxVer;
cfh.minSVer = ServerConfigManager.Instance.MinVer;
cfh.maxCver = ServerConfigManager.Instance.MaxCVer;
cfh.minCver = ServerConfigManager.Instance.MinCVer;
return cfh;
}
/// <summary>
/// 设置系统时间间隔
/// </summary>
/// <param name="t"></param>
[DllImport("winmm")]
protected static extern void timeBeginPeriod(int t);
/// <summary>
/// 恢复系统时间间隔
/// </summary>
/// <param name="t"></param>
[DllImport("winmm")]
protected static extern void timeEndPeriod(int t);
/// <summary>
/// 定时器管理
/// </summary>
private TimerManager timermgr;
/// <summary>
/// 更新服务器信息的时间
/// </summary>
public int updateServerInfo_time;
/// <summary>
/// 更新服务器信息
/// </summary>
protected virtual void UpdateServerInfo(bool isStart = false)
{
timeBeginPeriod(1);
serverinfo.moduleId = myUtil.id;
serverinfo.nodenum = myUtil.nodeNum;
if (isStart)
serverinfo.startTime = DateTime.Now;
serverinfo.serverName = ServerName;
serverinfo.dopackCnt = 0;
serverinfo.minfps = minfps;
serverinfo.fps = Fps;
serverinfo.maxRuntime = maxruntiming;
serverinfo.ConnectCnt = UserSessionsInfo.GetAllSessionCount();
serverinfo.BindConnectCnt = UserSessionsInfo.GetBindSessionCount();
updateServerInfo_time = ServerConfigManager.Instance.UpdateServerInfoTime;
}
/// <summary>
/// 更新
/// </summary>
protected virtual void Update()
{
TimeInfo.Instance.Update();
// long key = Debug.StartTiming();
GameNetDispatcher.Instance.Update();
GlobalDispatcher.Instance.Update();
GameDispatcher.Instance.Update();
// double runtime = Debug.GetRunTime(key);
// if (runtime > 200)
// {
// Debug.Error($"Update: 处理慢:{runtime}");
// }
}
/// <summary>
/// 启动数据
/// </summary>
/// <returns></returns>
protected virtual bool Init()
{
return true;
}
private void DayChange()
{
GameDispatcher.Instance.Dispatch(GameMsgId.DayChange);
}
/// <summary>
/// fps计数
/// </summary>
private int fpscount = -1;
/// <summary>
/// 帧率
/// </summary>
public int Fps { get; protected set; }
private int m_minfps = -1;
/// <summary>
/// 最小fps
/// </summary>
public int minfps
{
get { return m_minfps; }
protected set { m_minfps = value; }
}
/// <summary>
/// 最大运行时间
/// </summary>
public double maxruntiming { get; protected set; }
private System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
/// <summary>
/// 发送配置包裹
/// </summary>
protected virtual void SendConfigPack()
{
}
/// <summary>
/// 处理模块死亡信号
/// </summary>
/// <param name="node"></param>
/// <param name="nodenum"></param>
protected void DoModuleDieSign(object param)
{
if (param is ServerNode serverNode)
{
Debug.Info("模块死亡包处理!");
PackHead head = PackHead.Create();
head.packlx = ServerPackAgreement.ModuleDie;
Message msg = GlobalMQ.CreateMessage(head, serverNode);
GlobalMQ.instance.AddMessage(msg);
head.Dispose();
}
}
/// <summary>
/// 发送开启节点包
/// </summary>
protected virtual void SendOpenNode()
{
//注册模块
PackHead head = PackHead.Create();
head.packlx = ServerPackAgreement.openNode;
var data = this.myType != ModuleType.WatchDog ? MonitoringAppInfo : null;
GlobalMQ.instance.DeliveryAll(GlobalMQ.CreateMessage(head, data), true);
head.Dispose();
}
/// <summary>
/// 发送关闭节点包
/// </summary>
protected void SendCloseNode()
{
PackHead head = PackHead.Create();
head.packlx = ServerPackAgreement.closeNode;
var data = this.myType != ModuleType.WatchDog ? MonitoringAppInfo : null;
GlobalMQ.instance.DeliveryAll(GlobalMQ.CreateMessage(head, data), true);
head.Dispose();
}
//自身主机信息应该是不变的。 暂存这个信息
MonitoringAppInfo MonitoringAppInfo =>
MonitoringAppInfo.GetCurrentApplicateInfo(this.myUtil.onlyId, this.myUtil.id, this.myUtil.nodeNum);
/// <summary>
/// 退出游戏
/// </summary>
public virtual void Quit()
{
state = ServerState.Stoping;
}
#region ITimerProcessor
/// <summary>
/// 100毫秒定时器
/// </summary>
public virtual void OnTime(int Interval)
{
//Debug.Log("秒级定时器:" + "," + System.DateTime.Now.Ticks);
}
/// <summary>
/// 记录天
/// </summary>
int Day = 0;
/// <summary>
/// 秒级定时器
/// </summary>
public virtual void SecondTime()
{
updateServerInfo_time--;
if (updateServerInfo_time == 0)
{
UpdateServerInfo();
}
DoFps();
if (Day != DateTime.Now.Day)
{
Day = DateTime.Now.Day;
DayInit();
}
}
#endregion
/// <summary>
/// 每一天初始化一次
/// </summary>
public virtual void DayInit()
{
}
/// <summary>
/// 处理Fps的赋值
/// </summary>
protected virtual void DoFps()
{
if (minfps < 0 || minfps > fpscount)
{
minfps = fpscount;
//Debug.Warning("fps最低记录:" + minfps);
}
Fps = fpscount;
fpscount = 0;
}
/// <summary>
/// 缓存变化
/// </summary>
/// <param name="msg"></param>
protected virtual void CacheChange(WaitBeMsg msg)
{
var head = msg.head;
if (head.otherString == null || head.otherString.Length == 0)
return;
Debug.Info("处理缓存更新!" + head.otherString[0]);
CaCheManager.instance.UpdateKeyAsync(head.otherString[0]);
}
/// <summary>
/// 处理其他
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
protected virtual bool HandleOtherServerPack(WaitBeMsg msg) => false;
/// <summary>
/// 处理模块死亡信号——意外死亡
/// </summary>
/// <param name="msg"></param>
protected virtual void ModuleDie(WaitBeMsg msg)
{
var data = JsonPack.GetData<ServerNode>(msg.jsondata);
if (data == null)
Debug.Error("数据错误!");
else
Debug.Warning("模块死亡信号:" + data.id + "," + data.nodeNum);
}
/// <summary>
///
/// </summary>
protected virtual void Ping(PackHead head, string jsondata)
{
ModuleUtile util = JsonPack.GetData<ModuleUtile>(jsondata);
if (util == null)
Debug.Error("收到网络监测包数据为空!");
head.packlx = ServerPackAgreement.Pong;
GlobalMQ.instance.DeliveryOne(new ServerNode(util.id, util.nodeNum), GlobalMQ.CreateMessage(head, myUtil),
true);
Debug.Info("发送探测包:" + myUtil.ToString());
}
/// <summary>
///
/// </summary>
/// <param name="head"></param>
/// <param name="jsondata"></param>
protected virtual void Pong(PackHead head, string jsondata)
{
ModuleUtile util = JsonPack.GetData<ModuleUtile>(jsondata);
if (util == null)
Debug.Error("收到网络探测回包数据为空!");
else
Debug.Info("Pong : " + util.ToString());
}
/// <summary>
/// 心跳处理包
/// </summary>
/// <param name="msg">消息</param>
protected virtual void Heart(WaitBeMsg msg)
{
PackHead head = msg.head;
ServerNode node = head.sendutil;
if (node == null)
{
Debug.Error("心跳包错误,没有发送者的描述!");
return;
}
if (node.Equals(myUtil)) //自己的包不处理
return;
//ServerHeart.instanece.DoHeartAsync(node.id, node.nodeNum);
}
/// <summary>
/// 节点开启信号
/// </summary>
/// <param name="msg">消息</param>
[System.Diagnostics.DebuggerNonUserCode]
protected virtual void RecvOpenNode(WaitBeMsg msg)
{
PackHead head = msg.head;
ModuleUtile node = head.sendutil;
if (node == null)
{
Debug.Error("节点开启信号包错误,没有发送者的描述!");
return;
}
if (node.Equals(myUtil))
{
return;
}
//Debug.Info($"接收到模块开启:{node.ToString()}");
RountingManager.instance.AddModule(node.id, node.name);
if (node.id == (int)ModuleType.ConfigModule)
{
SendConfigPack();
}
if (head.otherString == null || head.otherString.Length == 0 || head.otherString[0] != "ok")
{
head.packlx = ServerPackAgreement.openNode;
head.otherString = new string[] { "ok" };
var data = this.myType != ModuleType.WatchDog ? MonitoringAppInfo : null;
var sendmsg = GlobalMQ.CreateMessage(head, data, null, -1, -1, null, null);
GlobalMQ.instance.DeliveryOne(node, sendmsg, true);
}
ServerHeart.instanece.AddModule(node.id, node.name, node.nodeNum);
}
/// <summary>
/// 节点关闭信号_正常关闭
/// </summary>
/// <param name="msg">消息</param>
protected virtual void RecvCloseNode(WaitBeMsg msg)
{
ModuleUtile node = msg.head.sendutil;
if (node == null)
{
Debug.Error("收到节点关闭信号,没有发送者的描述!");
return;
}
if (node.Equals(myUtil))
{
//是本模块
if (node.onlyId != myUtil.onlyId)
{
return;
}
if (state == ServerState.Runing)
{
//检测到已经死了
//直接退出
Debug.Error("收到死完包!直接退出!");
state = ServerState.Error;
return;
}
else
return;
}
//模块死亡信号
ServerHeart.instanece.RemoveDie(node.id, node.nodeNum, true);
Debug.Warning("收到模块关闭信号:" + node);
}
/// <summary>
/// 处理命令
/// </summary>
protected virtual void DoCommand(WaitBeMsg msg)
{
string[] cmds = msg.head.otherString;
if (cmds == null || cmds.Length <= 0)
return;
Debug.Info("收到命令" + cmds[0]);
switch (cmds[0])
{
case "exit":
Quit();
break;
case "test":
break;
case "onlineModules": //在线的所有模块
Debug.Log("所有的在线模块");
break;
case "redislocktest":
break;
}
}
/// <summary>
/// DistributedLock
/// </summary>
protected DistributedLock dtl { get; } = new DistributedLock(1000);
#region IServer
/// <summary>
/// 服务器状态
/// </summary>
public ServerState state { get; set; } = ServerState.Close;
/// <summary>
/// 服务器名称
/// </summary>
public string ServerName
{
get
{
return ServerConfigManager.Instance.ServerName;
}
}
/// <summary>
/// 我的模块单元
/// </summary>
public ModuleUtile myUtil { get; protected set; }
private ModuleType mMyType;
/// <summary>
/// 模块类型
/// </summary>
public ModuleType myType
{
get { return mMyType; }
}
/// <summary>
/// 消息处理器
/// </summary>
public MessageProcessor msgProcessor;
/// <summary>
/// 其他配置初始化
/// </summary>
public virtual void OtherConfigInit()
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 50; i++)
{
stringBuilder.Append('0');
}
if (ServerConfigManager.Instance.GameConfig != null)
{
ServerConfigManager.Instance.GameConfig.GameGz = stringBuilder.ToString();
if (ServerConfigManager.Instance.TingCnt > 0)
{
foreach (var ting in ServerConfigManager.Instance.Tings)
{
ting.TingGz = stringBuilder.ToString();
}
}
}
}
/// <summary>
/// 检查配置表是否有问题
/// </summary>
/// <returns></returns>
public virtual bool CheckConfig()
{
return true;
}
/// <summary>
/// 启动
/// </summary>
public bool Start()
{
//启动中
state = ServerState.Starting;
mMyType = (ModuleType)ServerConfigManager.Instance.NodeId;
myUtil = new ModuleUtile(ServerConfigManager.Instance.NodeId,
ServerConfigManager.Instance.NodeNum,
Enum.GetName(myType.GetType(), myType),
ServerConfigManager.Instance.MaxVer);
TimeInfo.Instance.DayChange += DayChange;
//序列化预热
PreLoadMessagePack();
GlobalDispatcher.Instance.Dispatch(GlobalMsgId.GameNameReadSuccess, ServerConfigManager.Instance.ServerName);
Debug.Info($"Start ServerName:{ServerConfigManager.Instance.ServerName}");
//数据库初始化
GameDB.Instance.Init(SqlConfigCategory.Instance.GetDBSqlConfig());
//redis启动
redisManager.Start();
ClientConfig = GetConfigHead();
//存储自己的模块信息
if (!redisManager.db.HashExists(RedisDictionary.moduleNames, ServerConfigManager.Instance.NodeId.ToString()))
redisManager.db.HashSet(RedisDictionary.moduleNames, ServerConfigManager.Instance.NodeId, myUtil.name);
//心跳开始,并检查模块是否在线
if (!ServerHeart.instanece.Start(myType, ServerConfigManager.Instance.NodeNum))
{
Debug.ImportantLog("启动失败,模块在线!");
return false;
}
MessagePool.tag = "" + myUtil.id + "-" + myUtil.nodeNum + "-" + myUtil.ver + "-" + myUtil.name;
//模块死亡事件监听
GlobalDispatcher.Instance.AddListener(GlobalMsgId.ModuleNodeDie, DoModuleDieSign);
//创建消息处理
Factory.CreateGlobalMQFactory().CreateGlobalMQ();
//启动rabbit
if (!GlobalMQ.instance.StartModule(RabbitConfigCategory.Instance.GetRabbitMQConfig(), myUtil))
{
Debug.Error("启动失败:A71134F4-EA97-44C0-A305-E35966622FEB");
return false;
}
msgProcessor = Factory.CreateMessageProcessor();
new UserSessionsManager().Register();
//重要数据启动
if (!Init())
{
return false;
}
Debug.ImportantLog("init over!!!");
//发送开启信号
SendOpenNode();
//定时器管理
timermgr = new TimerManager(ServerConfigManager.Instance.OnTime);
timermgr.Start();
//更改状态为运行中
state = ServerState.Runing;
//更新服务器信息
UpdateServerInfo(true);
//开始发送心跳包
ServerHeart.instanece.BeginHeart(Factory.CreateHeartPack(myUtil));
return true;
}
private StringBuilder logs = new StringBuilder();
private int GcCount = 0;
/// <summary>
/// 预热 MessagePack
/// </summary>
protected virtual void PreLoadMessagePack()
{
}
private void ReLoadTable()
{
TableManager.Instance.ReLoadTableData();
try
{
ReLoadTableInit();
Debug.ImportantLog("配置重新加载成功!");
}
catch (Exception e)
{
Debug.Error("重载配置出错!" + e.Message);
TableManager.Instance.RollBack();
}
}
protected virtual void ReLoadTableInit()
{
}
/// <summary>
/// 主线程
/// </summary>
public void Loop()
{
if (state == ServerState.Runing)
{
try
{
logs.Clear();
watch.Restart();
//watch.Restart();
if (IsReloadTable)
{
IsReloadTable = false;
ReLoadTable();
}
if (timermgr.GetMillScoend())
{
#if DEBUG
var key = Debug.StartTiming();
logs.AppendLine($"GlobalManager Loop DoTime begin");
#endif
OnTime(timermgr.Interval);
#if DEBUG
logs.AppendLine($"GlobalManager Loop DoTime end, time: {Debug.GetRunTime(key)}");
#endif
}
if (timermgr.GetSecoend())
{
#if DEBUG
var key = Debug.StartTiming();
logs.AppendLine($"GlobalManager Loop DoTimeSecond begin");
#endif
SecondTime();
#if DEBUG
logs.AppendLine($"GlobalManager Loop DoTimeSecond end, time: {Debug.GetRunTime(key)}");
#endif
}
//消息处理
msgProcessor.Run(logs);
#if DEBUG
var updateKey = Debug.StartTiming();
#endif
fpscount++;
Update();
#if DEBUG
logs.AppendLine($"Update Loop time:{Debug.GetRunTime(updateKey)}");
#endif
watch.Stop();
double runtime = watch.ElapsedMilliseconds; //.ElapsedMilliseconds;
if (runtime >= 100)
{
logs.AppendLine(
$"GlobalManager Loop end, now: {DateTime.Now}, runtime: {runtime} / {watch.Elapsed.TotalMilliseconds}");
Debug.Error($"Loop runtime warning: " + logs.ToString());
}
if (runtime > maxruntiming)
maxruntiming = runtime;
}
catch (Exception e)
{
Debug.Error("主线程错误:" + e.ToString());
}
}
else if (state == ServerState.Stoping)
{
Close();
}
}
/// <summary>
/// 阻塞检查,直到正常退出
/// </summary>
public virtual void Close()
{
UUIDManager.Instance.Close();
UserSessionsManager.Instance.Dispose();
timermgr.Stop();
SendCloseNode();
ServerHeart.instanece.Close();
//ServerManager.instance.Close();
if (GlobalMQ.instance != null)
GlobalMQ.instance.Close();
//保存道具日志
PropManager.Instance.Dispose();
state = ServerState.Stop;
Debug.Log("模块正常退出!");
}
#endregion
/// <summary>
/// 收到获取在线人数的请求
/// </summary>
/// <param name="msg"></param>
protected virtual void ReportPlayerOnLineData(WaitBeMsg msg)
{
}
}
}