using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sog; using Sog.Service; using ProtoCSStruct; namespace Mail { //每个Task需要一个Handler,一个Handler一个DBOperator public class MessageTaskHandler { /// /// 不要修改这个数量,除非你真的搞明白了db的多工作线程和db多进程的关系!! /// public const int MailDBWorkThreadCount = 10; private MailDBOperator m_dbOperator; private long m_lastKeepMysqlConnTimeSecond; //自管理 private static MessageTaskHandler[] m_allTaskHandler; //先做个全局,要是锁等待比较耗时的话再分线程 public static MessageTaskStat m_messageTaskStat; //旧的mysql连接 private MailDBOperator m_oldDBOperator = null; public static void InitAllTaskHandler(ServerApp app) { //分配消息任务,线程数量 uint iTaskCount = (uint)MailDBWorkThreadCount; TraceLog.Debug("MessageTaskHandler.InitAllHandler messageTaskCount is {0}", iTaskCount); MessageTaskDistributor.Instance.InitTask(iTaskCount, app); MailServerConfig serverConfig = MailServerUtils.GetServerConfig(); m_allTaskHandler = new MessageTaskHandler[iTaskCount]; MailServerUtils.ParseDBConfig(app, out int dbtype, out string dbname, out string dbip); for (int i = 0; i < m_allTaskHandler.Length; i++) { m_allTaskHandler[i] = new MessageTaskHandler(); if (dbtype == 0) { m_allTaskHandler[i].m_dbOperator = new MysqlMailDBOperator(dbname, dbip, serverConfig.dbuser, serverConfig.dbpassword); } else { TraceLog.Error("MessageTaskHandler.InitAllTaskHandler invalid dbtype {0}", dbtype); } MessageTaskObj taskObj = MessageTaskDistributor.Instance.GetTaskByIndex(i); taskObj.Handler = m_allTaskHandler[i].HandlerPacket; taskObj.IdleTick = m_allTaskHandler[i].OnIdleTick; } ResetTaskStat(); MessageTaskDistributor.Instance.StartAllTask(); } public static void ResetTaskStat() { if(m_messageTaskStat == null) { m_messageTaskStat = new MessageTaskStat(); } var config = MailServerUtils.GetServerConfig(); if (config.isCloseAllTaskMsgStat) { m_messageTaskStat.ResetNeedMsgList(false); if (config.taskStatMsgs != null) { for (int i = 0; i < config.taskStatMsgs.Length; i++) { if (config.taskStatMsgs[i] > 0) { m_messageTaskStat.AddNeedMsg(config.taskStatMsgs[i]); } } } } else { m_messageTaskStat.ResetNeedMsgList(true); } } public static void Tick(long nowMs) { if(m_messageTaskStat != null) { m_messageTaskStat.Tick(nowMs); } } public static void DisposeAllHandler() { //关闭所有消息处理任务 MessageTaskDistributor.Instance.CloseAllTask(); if(m_allTaskHandler == null) { return; } //销毁数据库连接,销毁对象 for (int i = 0; i < m_allTaskHandler.Length; i++) { m_allTaskHandler[i].m_dbOperator.Dispose(); m_allTaskHandler[i].m_dbOperator = null; } m_allTaskHandler = null; } public static void AfterReloadServerConfigChangeDB(ServerApp app) { MailServerConfig serverConfig = MailServerUtils.GetServerConfig(); MailServerUtils.ParseDBConfig(app, out int dbtype, out string dbname, out string dbip); for (int i = 0; i < m_allTaskHandler.Length; i++) { m_allTaskHandler[i].m_oldDBOperator = m_allTaskHandler[i].m_dbOperator; m_allTaskHandler[i].m_lastKeepMysqlConnTimeSecond = AppTime.GetNowSysSecond() ; //建立新的链接 if (dbtype == 0) { m_allTaskHandler[i].m_dbOperator = new MysqlMailDBOperator(dbname, dbip , serverConfig.dbuser, serverConfig.dbpassword); } else { TraceLog.Error("MessageTaskHandler.AfterReloadServerConfigChangeDB invalid dbtype {0}", dbtype); } } } public void OnIdleTick(long idleSecond) { //5分钟保持连接一次 if (AppTime.GetNowSysSecond() - m_lastKeepMysqlConnTimeSecond < 300) { return; } if (m_oldDBOperator != null) { m_oldDBOperator.Dispose(); m_oldDBOperator = null; } m_lastKeepMysqlConnTimeSecond = AppTime.GetNowSysSecond(); m_dbOperator.KeepAlive(); } public void HandlerPacket(uint remoteAppID, StructPacket packet) { //去掉这里的时间重置逻辑,如果下面实际处理逻辑里没有进行sql查询就返回会造成KeepAlive不执行 //m_lastKeepMysqlConnTimeSecond = AppTime.GetNowSysSecond(); bool isNeedStat = m_messageTaskStat.IsNeedStat(packet.MsgID); long sTime = isNeedStat ? AppTime.GetNowSysMs() : 0; switch (packet.MsgID) { case (int)SSGameMsgID.QueryMailReq: MailOp.OnQueryMailReq(remoteAppID, packet, m_dbOperator); break; case (int)SSGameMsgID.MailOpReq: MailOp.OnMailOpReq(remoteAppID, packet, m_dbOperator); break; case (int)SSGameMsgID.QueryMailVersionReq: MailOp.OnQueryMailVersionReq(remoteAppID, packet, m_dbOperator); break; case (int)SSGameMsgID.OperationMailSearchReq: MailOp.OnOperationQueryMailReq(remoteAppID, packet, m_dbOperator); break; default: TraceLog.Error("MessageTaskHandler unknow MsgID {0}", packet.MsgID); break; } if(isNeedStat) { long eTime = AppTime.GetNowSysMs(); m_messageTaskStat.OnNetRecv(packet.MsgID, packet.Header.Length + 16, eTime - sTime); } } } }