440 lines
13 KiB
Lua
440 lines
13 KiB
Lua
local skynet = require "skynet"
|
||
require "skynet.manager"
|
||
skynet.server = {}
|
||
require "Include"
|
||
local json =require "json"
|
||
local gameCmd = require "GameCmd"
|
||
local log = require "Log"
|
||
local errorInfo = require "ErrorInfo"
|
||
local cluster = require "skynet.cluster"
|
||
local socket = require "skynet.socket"
|
||
local pb = require "pb"
|
||
local mongo = require "skynet.db.mongo"
|
||
local redis = require "skynet.db.redis"
|
||
local redisKeyUrl = require "RedisKeyUrl"
|
||
local serverId = tonumber(skynet.getenv "serverId")
|
||
local clusterServer = require "ClusterServer"
|
||
local db = require "DB"
|
||
|
||
--AES 04169967a0dda41831aae37ae5f7c37a
|
||
--接收HTTP消息
|
||
function skynet.StartRecv()
|
||
skynet.register("StartServer")
|
||
skynet.dispatch("lua", function (_,_, cmd, ...)
|
||
if "TcpMsg" == cmd then --Tcp消息
|
||
local c2sData = ...
|
||
local isDo,s2cData = false,nil
|
||
s2cData = skynet.server.tcpServer:TcpRecv( c2sData )
|
||
local sendMsg,sendLen = skynet.pack(s2cData)
|
||
skynet.ret(sendMsg,sendLen)
|
||
|
||
elseif "HttpMsg" == cmd then --Http消息
|
||
local id ,url , c2sData , addr ,header= ...
|
||
--对接收到消息进行处理
|
||
local isDo,s2cData = false,nil
|
||
function Do(url ,c2sData , addr)
|
||
--获取IP地址
|
||
local pos = string.find(addr,":")
|
||
addr = string.sub(addr,1,pos - 1)
|
||
local bodyStr=c2sData
|
||
c2sData = json:decode(c2sData)
|
||
if c2sData ~=nil and bodyStr ~= nil then
|
||
c2sData.bodyStr=bodyStr
|
||
end
|
||
s2cData = skynet.server.httpServer:Recv(url, c2sData , addr , header)
|
||
return s2cData
|
||
end
|
||
|
||
--pcall调用一下,有异常直接返回
|
||
|
||
isDo,s2cData = pcall(Do,url ,c2sData , addr , header)
|
||
local sendMsg,sendLen = 0,0
|
||
if isDo then
|
||
sendMsg,sendLen = skynet.pack(s2cData)
|
||
else
|
||
log.info("StartServer HttpMsg内部错误信息",s2cData)
|
||
s2cData ={}
|
||
s2cData.code = errorInfo.ErrorCode.InnerError
|
||
s2cData = json:encode(s2cData)
|
||
sendMsg,sendLen = skynet.pack(s2cData)
|
||
end
|
||
--返回去
|
||
skynet.ret(sendMsg,sendLen)
|
||
elseif "ClusterMsg" == cmd then --集群消息
|
||
local sendMsg,sendLen = 0,0
|
||
sendMsg,sendLen = skynet.pack(clusterServer:ClusterRecv(...))
|
||
skynet.ret(sendMsg,sendLen)
|
||
--elseif "RedisMsg" == cmd then --Redis消息 (废弃,后面再清理)
|
||
-- skynet.server.gameServer:RedisMsgRecv(...)
|
||
end
|
||
end)
|
||
end
|
||
|
||
--初始化各种模块
|
||
function skynet.Init()
|
||
skynet.newservice("Logger")
|
||
local isOk = true
|
||
|
||
--载入游戏需要的配置文件
|
||
skynet.server.gameConfig:LoadConfig()
|
||
skynet.server.gameConfig:LoadJson()
|
||
skynet.server.gameConfig:LoadProto()
|
||
|
||
skynet.desKey = "12345678"
|
||
skynet.AddTime = 0
|
||
skynet.ServerName = clusterServer:GetServerTypeName( serverId )
|
||
|
||
--初始化Redis
|
||
skynet.InitRedis()
|
||
|
||
--游戏服可以连接多个数据库
|
||
skynet.InitDB( false )
|
||
|
||
--初始化MongoDB
|
||
skynet.InitMongoDB()
|
||
|
||
--先初始化clusterServer ,再初始其它模块
|
||
skynet.server.clusterServer:Init()
|
||
|
||
if skynet.server.clusterServer:IsGameServer( serverId ) then
|
||
--游戏服才会用到该模块
|
||
skynet.server.redisCache:Init()
|
||
end
|
||
|
||
for key, value in pairs(skynet.server) do
|
||
if not string.find(key, "redis") and not string.find(key, "mongo") and "clusterServer" ~= key and value.Init then
|
||
value:Init()
|
||
end
|
||
end
|
||
|
||
log.info("程序模块初始化完成")
|
||
|
||
--获取当前服务器IP信息
|
||
local cfgServer = skynet.server.common:GetClusterConfig( serverId )
|
||
if not cfgServer then
|
||
log.info("当前获取集群配置出错1 ",serverId)
|
||
return false
|
||
end
|
||
log.info("获取当前服务器配置完成")
|
||
|
||
--http底层加载
|
||
if "" ~= cfgServer.httpPort then
|
||
if skynet.server.clusterServer.multiServerID == serverId then
|
||
--多功能服需要传输大数据,单独修改一下最大传输数量为1M
|
||
skynet.server.httpSocket = skynet.newservice("HttpMultiSocket", "0.0.0.0" , cfgServer.httpPort)
|
||
else
|
||
skynet.server.httpSocket = skynet.newservice("HttpSocket", "0.0.0.0" , cfgServer.httpPort)
|
||
end
|
||
end
|
||
log.info("Http模块初始化完成")
|
||
|
||
--登陆服和游戏服不绑定TCP端口
|
||
if "" ~= cfgServer.tcpPort then
|
||
skynet.server.tcpSocket = skynet.newservice("TcpSocket", "0.0.0.0" , cfgServer.tcpPort)
|
||
end
|
||
log.info("Tcp模块初始化完成")
|
||
|
||
if "" ~= cfgServer.webSocketPort then
|
||
skynet.server.webSocket = skynet.newservice("WebSocket", "0.0.0.0" , cfgServer.webSocketPort)
|
||
end
|
||
log.info("WebSocket模块初始化完成")
|
||
|
||
--通过配置获取的节点进行组装
|
||
local clusterList = {}
|
||
local serverName = ""
|
||
for k, v in pairs(skynet.server.gameConfig.ClusterServerConfig) do
|
||
if serverId == v.serverId then
|
||
skynet.externalIp = v.externalIp
|
||
end
|
||
serverName = clusterServer:GetServerTypeClusterName( v.serverId )
|
||
clusterList[ serverName ] = string.format("%s:%s",v.internalIp ,v.clusterPort)
|
||
end
|
||
|
||
--载入集群
|
||
local clusterName = clusterServer:GetServerTypeClusterName( serverId )
|
||
cluster.reload(clusterList)
|
||
cluster.register(clusterName)
|
||
cluster.open(clusterName)
|
||
skynet.server.cluster = cluster
|
||
log.info("载入集群节点配置完成")
|
||
end
|
||
|
||
--主服务器
|
||
skynet.start(function()
|
||
skynet.StartRecv()
|
||
skynet.Init()
|
||
skynet.fork(skynet.ClusterTimer,500)
|
||
skynet.fork(skynet.GameTimer,500)
|
||
skynet.fork(skynet.GameTimer5Minute,100*60*5)--五分钟定时任务
|
||
skynet.fork(skynet.SaveMongoDBTimer,500) --500
|
||
skynet.fork(skynet.SaveMysqlDBTimer,500) --500
|
||
skynet.fork(skynet.SyncTimer,500) --500
|
||
--skynet.fork(skynet.Subscribe)(废弃,后面再清理)
|
||
log.info("服务器成功开启")
|
||
end)
|
||
|
||
--初始化Redis
|
||
function skynet.InitRedis()
|
||
--redis连接
|
||
local redisCfg =
|
||
{
|
||
host = skynet.server.gameConfig.RedisConfig.host ,
|
||
port = skynet.server.gameConfig.RedisConfig.port ,
|
||
db = skynet.server.gameConfig.RedisConfig.dbIndex,
|
||
auth = skynet.server.gameConfig.RedisConfig.password
|
||
}
|
||
|
||
skynet.server.redis = redis.connect(redisCfg)
|
||
if not skynet.server.redis then
|
||
log.info("连接Redis数据库失败")
|
||
return false
|
||
else
|
||
log.info(string.format("Redis 数据库连接成功 信息 IP地址 %s 端口 %s" ,redisCfg.host , redisCfg.port))
|
||
end
|
||
|
||
--RedisUser连接,目前数量为2,根据配置文件来确定
|
||
for i = 1, 2, 1 do
|
||
local tmpConfig = skynet.server.gameConfig[ "RedisUser"..i.."Config" ]
|
||
if tmpConfig then
|
||
local redisUserCfg = { host = tmpConfig.host , port = tmpConfig.port , db = tmpConfig.dbIndex , auth = tmpConfig.password }
|
||
skynet.server[ "redisUser"..i ] = redis.connect( redisUserCfg )
|
||
if not skynet.server[ "redisUser"..i ] then
|
||
log.info("连接RedisUser数据库失败",i)
|
||
return false
|
||
else
|
||
log.info(string.format("RedisUser%d 数据库连接成功 信息 IP地址 %s 端口 %s" , i , redisUserCfg.host , redisUserCfg.port))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--初始化DB
|
||
function skynet.InitDB( isReConnect )
|
||
local isOk = true
|
||
local dbConfig = skynet.server.gameConfig.DBInfoConfig
|
||
local cfgOneServer = skynet.server.gameConfig:GetCurClusterServerCfg( serverId )
|
||
|
||
--分析要连接的数据库名
|
||
if "" ~= cfgOneServer.dbName then
|
||
local dbNameList = skynet.server.common:Split( cfgOneServer.dbName , "|")
|
||
for k, dbName in pairs( dbNameList ) do
|
||
if isReConnect then
|
||
skynet.server.db:DisConnect( dbName )
|
||
skynet.sleep(10) --间隔10毫秒
|
||
end
|
||
|
||
isOk = skynet.server.db:Connect( dbConfig.host ,dbConfig.port ,dbConfig.user,dbConfig.password , dbName )
|
||
if not isOk then
|
||
return false
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--初始化MongoDB
|
||
function skynet.InitMongoDB()
|
||
if skynet.server.gameConfig:IsMongoDB() then
|
||
local dbCfg =
|
||
{
|
||
host = skynet.server.gameConfig.MongDBConfig.host ,
|
||
port =skynet.server.gameConfig.MongDBConfig.port ,
|
||
username = skynet.server.gameConfig.MongDBConfig.username,
|
||
password = skynet.server.gameConfig.MongDBConfig.password,
|
||
--authdb = skynet.server.gameConfig.MongDBConfig.authdb
|
||
}
|
||
local authdb = skynet.server.gameConfig.MongDBConfig.authdb
|
||
skynet.server.mongo = mongo.client(dbCfg)[ authdb ]
|
||
--skynet.server.mongo.user1:safe_insert({_id = 1, name = "user2", password = "123456"}, true)
|
||
--skynet.server.mongo.user1:findOne({test_key = 1});
|
||
--skynet.server.mongo.user1:safe_update({ _id = 3} ,{name = "user3.2", password = "123456"} , true )
|
||
--local curData = skynet.server..mongo.user3:findOne()
|
||
log.info(string.format("MongoDB数据库连接成功 信息 IP地址 %s 端口 %s" , dbCfg.host , dbCfg.port))
|
||
end
|
||
end
|
||
|
||
--集群Timer
|
||
function skynet.ClusterTimer( timeStamp )
|
||
local isSuc ,err = nil,nil
|
||
local todayTime = skynet.GetTime()
|
||
while true do
|
||
|
||
--跨天
|
||
if not skynet.server.common:IsSameDay(skynet.GetTime() , todayTime ) then
|
||
log.info(string.format("集群Timer 服务器跨天 当前时间 %d 服务器记录时间 %d",skynet.GetTime() ,todayTime ))
|
||
--跨天TIMER
|
||
function Do()
|
||
skynet.server.clusterServer:OnNewDay()
|
||
end
|
||
|
||
isSuc,err = pcall(Do)
|
||
if not isSuc then
|
||
log.info("集群Timer 跨天有报错",err)
|
||
end
|
||
todayTime = skynet.GetTime()
|
||
end
|
||
|
||
--5秒TIMER
|
||
function Do()
|
||
skynet.server.clusterServer:On5SecTimer()
|
||
end
|
||
|
||
isSuc,err = pcall(Do)
|
||
if not isSuc then
|
||
log.info("集群Timer 5秒有报错",err)
|
||
end
|
||
skynet.sleep(timeStamp)
|
||
end
|
||
end
|
||
|
||
--游戏TImer主要是游戏逻辑
|
||
function skynet.GameTimer( timeStamp )
|
||
local isSuc ,err = nil,nil
|
||
local todayTime = skynet.GetTime()
|
||
|
||
while true do
|
||
--跨天
|
||
if not skynet.server.common:IsSameDay(skynet.GetTime() , todayTime ) then
|
||
local str = string.format("游戏TImer 服务器跨天 当前时间 %d 服务器记录时间 %d",skynet.GetTime() , todayTime )
|
||
log.info(str)
|
||
|
||
--跨天TIMER
|
||
--clusterServer:OnNewDay()
|
||
for key, value in pairs(skynet.server) do
|
||
if "table"== type(value) and value.OnNewDay and not string.find(key, "redis") and not string.find(key, "mongo") and
|
||
"clusterServer" ~= key and "accountCenter" ~= key and "timer" ~= key then
|
||
function Do(value)
|
||
value:OnNewDay()
|
||
end
|
||
|
||
isSuc,err = pcall(Do,value)
|
||
if not isSuc then
|
||
log.info("游戏TImer 跨天TIMER有报错",key,err)
|
||
end
|
||
end
|
||
end
|
||
todayTime = skynet.GetTime()
|
||
end
|
||
|
||
--5秒TIMER
|
||
for key, value in pairs(skynet.server) do
|
||
if "table" == type(value) and value.On5SecTimer and not string.find(key, "redis") and not string.find(key, "mongo") and
|
||
"clusterServer" ~= key and "accountCenter" ~= key and "timer" ~= key then
|
||
function Do(value)
|
||
local t1 = skynet.GetTime()
|
||
value:On5SecTimer()
|
||
local t2 = skynet.GetTime() - t1
|
||
if t2 > 1 then
|
||
skynet.server.clusterServer:SendErrorInfoToCenter( nil , errorInfo.ErrorCode.CalcTimeTooLong , string.format("%s 计算时间过长", key))
|
||
log.info("游戏Timer 运行时间",key, t2 )
|
||
end
|
||
end
|
||
|
||
isSuc,err = pcall(Do,value)
|
||
if not isSuc then
|
||
log.info("游戏TImer 5秒TIMER有报错",key,err)
|
||
end
|
||
end
|
||
end
|
||
|
||
skynet.sleep(timeStamp)
|
||
end
|
||
end
|
||
|
||
--游戏TImer主要是游戏逻辑-五分钟
|
||
function skynet.GameTimer5Minute( timeStamp )
|
||
local isSuc ,err = nil,nil
|
||
|
||
while true do
|
||
|
||
--五分钟秒TIMER
|
||
for key, value in pairs(skynet.server) do
|
||
if "table" == type(value) and value.On5MinTimer and not string.find(key, "redis") and not string.find(key, "mongo") and
|
||
"clusterServer" ~= key and "accountCenter" ~= key and "timer" ~= key then
|
||
function Do(value)
|
||
local t1 = skynet.GetTime()
|
||
value:On5MinTimer()
|
||
local t2 = skynet.GetTime() - t1
|
||
if t2 > 1 then
|
||
skynet.server.clusterServer:SendErrorInfoToCenter( nil , errorInfo.ErrorCode.CalcTimeTooLong , string.format("%s 计算时间过长", key))
|
||
log.info("游戏Timer 运行时间",key, t2 )
|
||
end
|
||
end
|
||
|
||
isSuc,err = pcall(Do,value)
|
||
if not isSuc then
|
||
log.info("游戏TImer 5分钟TIMER有报错",key,err)
|
||
end
|
||
end
|
||
end
|
||
|
||
skynet.sleep(timeStamp)
|
||
end
|
||
end
|
||
|
||
--保存Mongo数据库Timer
|
||
function skynet.SaveMongoDBTimer( timeStamp )
|
||
--只有游戏服并且配置了Mongo数据库才开启timer
|
||
if skynet.server.gameConfig:IsMongoDB() and serverId >= clusterServer.gameServerMinID and serverId <= clusterServer.gameServerMaxID then
|
||
log.info("开启Mongo数据库Timer")
|
||
while true do
|
||
skynet.server.accountCenter:CheckSaveMongoDB()
|
||
skynet.sleep(timeStamp)
|
||
end
|
||
end
|
||
end
|
||
|
||
--保存Mysql数据库Timer
|
||
function skynet.SaveMysqlDBTimer( timeStamp )
|
||
if serverId >= clusterServer.gameServerMinID and serverId <= clusterServer.gameServerMaxID then
|
||
log.info("开启Mysql数据库Timer")
|
||
while true do
|
||
skynet.server.accountCenter:CheckSaveMysqlDB()
|
||
skynet.sleep(timeStamp)
|
||
end
|
||
end
|
||
end
|
||
|
||
--同步redis数据TImer
|
||
function skynet.SyncTimer( timeStamp )
|
||
while true do
|
||
skynet.server.timer:Refresh()
|
||
skynet.sleep(timeStamp)
|
||
end
|
||
end
|
||
|
||
--订阅Redis信息(废弃,后面再清理)
|
||
function skynet.Subscribe()
|
||
if not skynet.server.clusterServer:IsGameServer(serverId) then
|
||
return
|
||
end
|
||
|
||
--游戏服才发布-订阅功能
|
||
local redisCfg =
|
||
{
|
||
host = skynet.server.gameConfig.RedisConfig.host ,
|
||
port = skynet.server.gameConfig.RedisConfig.port ,
|
||
db = skynet.server.gameConfig.RedisConfig.dbIndex,
|
||
auth = skynet.server.gameConfig.RedisConfig.password
|
||
}
|
||
|
||
local w = redis.watch(redisCfg)
|
||
w:subscribe("mail") --订阅邮件
|
||
while true do
|
||
function Do()
|
||
local msg,channel = w:message()
|
||
skynet.send("StartServer", "lua","RedisMsg", msg , channel )
|
||
skynet.sleep(10)
|
||
return true
|
||
end
|
||
|
||
local isSuc,err = pcall(Do)
|
||
if not isSuc then
|
||
log.info("订阅Redis信息Timer 有报错",err)
|
||
end
|
||
end
|
||
end
|
||
|
||
--获取时间
|
||
function skynet.GetTime()
|
||
return os.time() + skynet.AddTime
|
||
end |