HomeServer/lualib-src/Server-main/Lib/Cluster/ClusterServer.lua

474 lines
16 KiB
Lua
Raw Normal View History

2024-11-20 15:41:09 +08:00
local skynet = require "skynet"
local mysql = require "skynet.db.mysql"
local oo = require "Class"
local cmd = require "GameCmd"
local errorInfo = require "ErrorInfo"
local pb = require "pb"
local log = require "Log"
local serverId = tonumber(skynet.getenv "serverId")
local ClusterServer = oo.class()
--中心服简称C 主服简称M 登陆服L 游戏服G
ClusterServer.centerServerID = 0 --中心服
ClusterServer.routerServerMinID = 1 --路由服 1-5
ClusterServer.routerServerMaxID = 5 --路由服 1-5
ClusterServer.monitorServerID = 6 --监控服和防黑功能
ClusterServer.multiServerID = 7 --多功能服
ClusterServer.rankServerID = 8 --榜单服
ClusterServer.payServerID = 9 --充值服
ClusterServer.gameServerMinID = 100 --游戏服开始
ClusterServer.gameServerMaxID = 199 --游戏服结束
--通用消息
ClusterServer.All_Start = 1000
ClusterServer.All_Reg = 1001 --注册
ClusterServer.All_UnReg = 1002 --注销
ClusterServer.All_Ping = 1003 --Ping
ClusterServer.All_SyncServerInfoToCenter = 1004 --同步服务器信息到中心服
ClusterServer.All_ErrorInfo = 1005 --错误信息
ClusterServer.All_End = 1999
--中心服消息
ClusterServer.CenterServer_Start = 1100
ClusterServer.Center2All_ServerManageCmd = 1101 --发送管理命令
ClusterServer.Center2All_SyncClusterInfo = 1102 --同步集群服信息
ClusterServer.Center2All_SyncServerConfig = 1103 --同步服务器配置
ClusterServer.Center2All_WebMsg = 1104 --后台数据
ClusterServer.CenterServer_End = 1199
--路由服消息
ClusterServer.RouteServer_Start = 1200
ClusterServer.Route2Monitor_VerifyValid = 1201 --验证该连接是否有效
ClusterServer.Route2Game_QueryUserOnline = 1202 --查询用户是否在线
ClusterServer.Route2Game_UserLoginToken = 1203 --发送登陆Token
ClusterServer.RouteServer_End = 1299
--监控服消息
ClusterServer.MoniterServer_Start = 1300
ClusterServer.All2Moniter_AddAccountToBlack = 1301 --添加账号到黑名单
ClusterServer.All2Moniter_AddIPToBlack = 1302 --添加IP到黑名单
ClusterServer.MoniterServer_End = 1399
--多功能服消息
ClusterServer.MultiServer_Start = 1400
ClusterServer.MultiServer_End = 1499
--榜单服消息
ClusterServer.RankServer_Start = 1500
ClusterServer.RankServer_End = 1599
--充值服消息
ClusterServer.PayServer_Start = 1600
ClusterServer.Pay2Game_AddPayInfo = 1601 --新增充值信息
ClusterServer.PayServer_End = 1699
--游戏服消息
ClusterServer.GameServer_Start = 2000
---------------------------------------------------------------------------------------------------------------游戏服发往帐号服消息-----------------------------------------
ClusterServer.GameToMonitor_UpdateUserStatus = 2001 --修改玩家状态 1-正常玩家 2-白名单 3-灰名单 4-黑名单
ClusterServer.GameToMulti_GetRedeemBonus = 2100 --获取兑换码奖励
ClusterServer.GameToMulti_GetMailList = 2101 --获取邮件列表
ClusterServer.GameToMulti_GetMailBonus = 2102 --获取邮件奖励
ClusterServer.GameToRank_UpdateScore = 3100 --更新玩家的分数
ClusterServer.GameToRank_GetRankData = 3101 --获取排行榜数据
ClusterServer.GameServer_End = 3999
ClusterServer.Status_Running = 1 --服务器运行
ClusterServer.Status_PingTimeout = 2 --PING超时
ClusterServer.Status_Stop = 3 --服务器停止
function ClusterServer:Init()
self.clusterInfo = {} --集群服所有服务器的信息
self.serverInfo = {} --当前服务器的信息
self.platformInfo = {} --平台信息
self.allServerConfig = {} --所有服务器配置
self.curClusterConfig = {} --当前集群配置
self.curServerConfig = {} --当前服务器配置
self.serverName = self:GetServerTypeName( serverId ) --服务器名称
self.isConnectCenter = false --是否连接中心服
self.lastSendPingTime = skynet.GetTime()
self.lastSyncServerInfoTime = skynet.GetTime()
self.isConnectCenterServer = false --是否连接中心服务器
self.isForceDisconnectCenter =false --是否强制断开中心服务器的连接
self.isTodayDeleteLog = false --今日是否删除日志
self.isTodayDeleteDB = false --今日是否删除数据库无用的记录
end
--跨天
function ClusterServer:OnNewDay()
self.isTodayDeleteLog = false
self.isTodayDeleteDB = false
end
--1秒Timer
function ClusterServer:On1SecTimer()
end
--5秒Timer
function ClusterServer:On5SecTimer()
function Do()
--删除日志文件
self:DeleteLogFile()
if self:IsCenterServer( serverId ) then
return
end
--连接断开 或者 未强制断开可以注册
if not self.isConnectCenterServer and not self.isForceDisconnectCenter then
--注册服务器
self:Reg()
else
--向中心服发送ping消息
if skynet.GetTime() - self.lastSendPingTime >= self.curClusterConfig.ClusterSlaveSendPingTime then
self:Ping()
end
--向中心服同步服务器信息
if skynet.GetTime() - self.lastSyncServerInfoTime >= self.curClusterConfig.SyncServerInfoTime then
self:SyncServerInfoToCenter()
end
end
end
local isSuc,err = pcall(Do)
if not isSuc then
self.isConnectCenterServer = false
log.info("与上级服务器断开连接,准备重新注册",err)
end
end
--接收集群服的消息
function ClusterServer:ClusterRecv( ... )
local cmd , clusterMsg = ...
local s2sData = {}
s2sData.code = errorInfo.Suc
s2sData.data = {}
if 0 == serverId and clusterMsg.serverId == serverId then
--主服不接收主服发来的消息
return s2sData
end
if not cmd or not clusterMsg then
s2sData.code = errorInfo.ErrorCode.ErrRequestParam
return s2sData
end
local serverName = self:GetServerTypeName( serverId )
serverName = serverName:gsub("^%u",string.lower) --将首字母从大写变成小写
s2sData = skynet.server[ serverName ]:ClusterRecv(...)
s2sData.desc = errorInfo.ErrorMsg[ s2sData.code ] or "暂无消息提示"
return s2sData
end
--向主服务器注册
function ClusterServer:Reg()
local s2sData = {}
local cfgCluster = skynet.server.common:GetClusterConfig( serverId )
if not cfgCluster then
s2sData.code = -1
return s2sData
end
local clusterMsg = {}
clusterMsg.serverId = serverId
clusterMsg.serverName = self.serverName.."_"..serverId
local clusterName = self:GetServerTypeClusterName( serverId )
local s2sData = self:CallMsgToCenterServer( self.All_Reg , clusterMsg)
if errorInfo.Suc == s2sData.code then
self.isConnectCenterServer = true
self.isForceDisconnectCenter = false
--同步服务器信息到中心服
self:SyncServerInfoToCenter()
log.info(string.format("集群服务器 %s 向中心服注册成功", clusterName))
else
log.info(string.format("集群服务器 %s 向中心服注册失败", clusterName))
end
end
--向主服务器注销
function ClusterServer:UnReg()
local s2sData = {}
local cfgCluster = skynet.server.common:GetClusterConfig( serverId )
if not cfgCluster then
s2sData.code = -1
return s2sData
end
local clusterMsg = {}
clusterMsg.serverId = serverId
clusterMsg.serverName = self.serverName.."_"..serverId
local clusterName = self:GetServerTypeClusterName( serverId )
local s2sData = self:CallMsgToCenterServer( self.All_UnReg , clusterMsg)
if errorInfo.Suc == s2sData.code then
self.isConnectCenterServer = false
self.isForceDisconnectCenter = true
self:SyncServerInfoToCenter()
log.info(string.format("集群服务器 %s 向中心服注销成功", clusterName))
else
log.info(string.format("集群服务器 %s 向中心服注销失败", clusterName))
end
end
--向主服务器发心跳包
function ClusterServer:Ping()
self.lastSendPingTime = skynet.GetTime()
local clusterMsg = {}
clusterMsg.serverId = serverId
local clusterName = self:GetServerTypeClusterName( serverId )
local s2sData,srcServerName,dstServerName = self:CallMsgToCenterServer( self.All_Ping , clusterMsg)
if errorInfo.Suc ~= s2sData.code then
log.info(string.format("集群服务器 %s 向中心服Ping失败", clusterName))
end
end
--同步服务器信息
function ClusterServer:SyncServerInfoToCenter()
self.lastSyncServerInfoTime = skynet.GetTime()
local c2sData = {}
c2sData.serverId = serverId
c2sData.serverInfo = self.serverInfo
self:SendMsgToCenterServer( self.All_SyncServerInfoToCenter , c2sData)
end
--错误信息发送到中心服
function ClusterServer:SendErrorInfoToCenter( errorCode , errorText )
local c2sData = {}
c2sData.serverId = serverId
c2sData.errorCode = errorCode
c2sData.errorText = errorText
self:SendMsgToCenterServer( self.All_ErrorInfo , c2sData)
end
function ClusterServer:GetServerName()
return self.serverName
end
--是否为中心服务器
function ClusterServer:IsCenterServer( serverId )
if self.centerServerID == tonumber(serverId) then
return true
else
return false
end
end
--是否为路由服务器
function ClusterServer:IsRouteServer( serverId )
if tonumber(serverId) >= self.routerServerMinID and tonumber(serverId) <= self.routerServerMaxID then
return true
else
return false
end
end
--是否为监视服务器
function ClusterServer:IsMonitorServer( serverId )
if self.monitorServerID == tonumber(serverId) then
return true
else
return false
end
end
--是否为多功能服务器
function ClusterServer:IsMultiServer( serverId )
if self.multiServerID == tonumber(serverId) then
return true
else
return false
end
end
--是否为排行榜服务器
function ClusterServer:IsRankServer( serverId )
if self.rankServerID == tonumber(serverId) then
return true
else
return false
end
end
--是否为多功能服务器
function ClusterServer:IsPayServer( serverId )
if self.payServerID == tonumber(serverId) then
return true
else
return false
end
end
--是否为游戏服务器
function ClusterServer:IsGameServer( serverId )
if tonumber(serverId) >= self.gameServerMinID and tonumber(serverId) <= self.gameServerMaxID then
return true
else
return false
end
end
--根据服务器ID获取类型名称
function ClusterServer:GetServerTypeName( serverId )
serverId = tonumber(serverId)
for k, v in pairs(skynet.server.gameConfig.ClusterServerConfig) do
if serverId == v.serverId then
return v.serverName
end
end
log.info("获取集群配置出错",serverId )
return ""
end
--根据服务器ID获取类型集群名称
function ClusterServer:GetServerTypeClusterName( serverId )
local serverName = self:GetServerTypeName(serverId)
return serverName.."_"..serverId
end
--接收同步集群信息
function ClusterServer:RecvSyncClusterInfo( c2sData )
--这类接收操作必须要按下面方式赋值,否则基类的地址会改变,导致基类无法调用
self.clusterInfo = {}
for k, v in pairs( c2sData.clusterInfo ) do
self.clusterInfo[ k ] = v
end
end
--接收同步服务器配置
function ClusterServer:RecvSyncServerConfig( c2sData )
--这类接收操作必须要按下面方式赋值,否则基类的地址会改变,导致基类无法调用
for k, v in pairs( c2sData.allServerConfig[ "ClusterServer" ] ) do
self.curClusterConfig[ k ] = v
end
--这类接收操作必须要按下面方式赋值,否则基类的地址会改变,导致基类无法调用
if c2sData.allServerConfig[ skynet.ServerName ] then
for k, v in pairs( c2sData.allServerConfig[ skynet.ServerName ] ) do
self.curServerConfig[ k ] = v
end
end
log.info("接收同步服务器配置")
end
--重新注册最新的节点
function ClusterServer:ReloadClusterNode()
skynet.server.gameConfig:LoadConfig()
skynet.server.gameConfig:LoadJson()
log.info("成功载入集群信息 ")
local clusterList = {}
local serverName = ""
for k, v in pairs(skynet.server.gameConfig.ClusterServerConfig) do
serverName = self:GetServerTypeClusterName( v.serverId )
clusterList[ serverName ] = string.format("%s:%s",v.internalIp ,v.clusterPort)
end
skynet.server.cluster.reload(clusterList)
log.info("成功载入集群信息 ",skynet.server.common:TableToString(clusterList))
end
--根据登陆和游戏服的ID获取网关服务器ID
function ClusterServer:GetGameServerID( serverId )
serverId = tonumber(serverId)
local gameServerId = nil
if serverId >= self.loginServerMinID and serverId <= self.loginServerMaxID then
gameServerId = math.floor((serverId % 100) / 2)
gameServerId = gameServerId + self.gameServerMinID
elseif serverId >= self.gameServerMinID and serverId <= self.gameServerMaxID then
gameServerId = math.floor((serverId % 100) / 10)
gameServerId = gameServerId + self.gameServerMinID
end
return gameServerId
end
--发向中心服
function ClusterServer:SendMsgToCenterServer( cmd , msg )
local centerName = "CenterServer_0"
skynet.server.cluster.send(centerName,"@"..centerName, "ClusterMsg", cmd , msg or {} )
end
--调用中心服
function ClusterServer:CallMsgToCenterServer( cmd , msg )
local centerName = "CenterServer_0"
return skynet.server.cluster.call(centerName,"@"..centerName, "ClusterMsg", cmd , msg or {})
end
--发向指定服务器
function ClusterServer:SendMsgToServer( serverId , cmd , msg )
if self.clusterInfo[ serverId ] then
local serverName = self:GetServerTypeClusterName( serverId )
skynet.server.cluster.send(serverName,"@"..serverName, "ClusterMsg", cmd , msg or {})
return true
else
return false
end
end
--调用指定服务器
function ClusterServer:CallMsgToServer( serverId , cmd , msg )
local isDo,s2cData = false,nil
function Do( serverId , cmd , msg )
local serverName = self:GetServerTypeClusterName( serverId )
return skynet.server.cluster.call(serverName,"@"..serverName, "ClusterMsg", cmd , msg or {} )
end
if self.clusterInfo[ serverId ] then
isDo,s2cData = pcall( Do , serverId , cmd , msg )
if isDo then
return s2cData
else
return nil
end
else
return nil
end
end
--删除过期日志文件
function ClusterServer:DeleteLogFile()
function Do()
local nowTime = skynet.GetTime()
--凌晨3点删除3天前的日志
if 3 == os.date("*t", nowTime).hour and not self.isTodayDeleteLog then
self.isTodayDeleteLog = true
log.info("开始删除文件夹")
local nowTime = skynet.GetTime()
local delTime=os.time({year=os.date("*t", nowTime).year, month=os.date("*t", nowTime).month, day=os.date("*t", nowTime).day - self.curClusterConfig.DeleteLogDayNum})
local path = string.format("rm -rf log/Server_%d/%d-%d-%d-%d",serverId,serverId,os.date("*t", delTime).year ,os.date("*t", delTime).month,os.date("*t", delTime).day)
os.execute(path)
log.info("删除文件"..path)
log.info("结束删除文件夹")
end
--主服才执行
if 4 == os.date("*t", nowTime).hour and not self.isTodayDeleteDB then
self.isTodayDeleteDB = true
end
end
local isSuc,err = pcall(Do)
if not isSuc then
log.info("删除过期文件内部错误 DeleteLogFile",err)
end
end
skynet.server.clusterServer= ClusterServer
return ClusterServer