From ddc3ea09255244e421e63f98ca14dc7a3084087f Mon Sep 17 00:00:00 2001 From: aozhiwei Date: Tue, 27 Oct 2020 21:10:44 +0800 Subject: [PATCH] 1 --- server/analyseapi/app.go | 26 +++--- server/analyseapi/constant.go | 7 ++ server/analyseapi/g.go | 8 +- server/analyseapi/gamelog.go | 48 ++++++++++ server/analyseapi/go.mod | 2 +- server/analyseapi/main.go | 5 -- server/analyseapi/makefile | 13 ++- server/analyseapi/metamgr.go | 24 +++-- server/analyseapi/metawrap.go | 20 +++++ server/analyseapi/statmgr.go | 164 ++++++++++++++++++++++++++++++++++ 10 files changed, 289 insertions(+), 28 deletions(-) create mode 100644 server/analyseapi/constant.go create mode 100644 server/analyseapi/gamelog.go create mode 100644 server/analyseapi/statmgr.go diff --git a/server/analyseapi/app.go b/server/analyseapi/app.go index cbfd30c..455d20e 100644 --- a/server/analyseapi/app.go +++ b/server/analyseapi/app.go @@ -1,29 +1,31 @@ package main -import "f5" -import "fmt" +import ( + "f5" +) type App_ struct { f5.App_ } -var App *App_ +var App = new (App_) func (this *App_) Init() { f5.App = &this.App_ - f5.App.SetPkgName("analyseapi") + f5.App.SetPkgName("statserver") this.App_.Init() - G.MetaMgr = new(MetaMgr) - G.MetaMgr.Init() - G.MetaMgr.Load() - G.GCListener = new(GCListener) - G.GCListener.Init() - fmt.Println( - G.MetaMgr.GetConf().GetGameHeartbeat()[0], - G.MetaMgr.GetServer(1)) + G.MetaMgr = new(MetaMgr).Init() + G.HttpServer = new(f5.HttpServer).Init() + G.GameLog = new(GameLog).Init() + G.StatMgr = new(StatMgr).Init() + + G.HttpServer.Start(G.MetaMgr.GetServer(1).GetListenPort()); } func (this *App_) UnInit() { + G.StatMgr.UnInit() + G.GameLog.UnInit() + G.HttpServer.UnInit() G.MetaMgr.UnInit() this.App_.UnInit() } diff --git a/server/analyseapi/constant.go b/server/analyseapi/constant.go new file mode 100644 index 0000000..ad226e8 --- /dev/null +++ b/server/analyseapi/constant.go @@ -0,0 +1,7 @@ +package main + +const ( + IM_UPDATE_SESSION = 100 +) + +const SESSION_KEY = "f3a6a9a5-217a-4079-ab99-b5d69b8212be" diff --git a/server/analyseapi/g.go b/server/analyseapi/g.go index ffd872e..2d4f933 100644 --- a/server/analyseapi/g.go +++ b/server/analyseapi/g.go @@ -1,8 +1,14 @@ package main +import ( + "f5" +) + type GlobalVar struct { MetaMgr *MetaMgr - GCListener *GCListener + HttpServer *f5.HttpServer + StatMgr *StatMgr + GameLog *GameLog } var G *GlobalVar = &GlobalVar{} diff --git a/server/analyseapi/gamelog.go b/server/analyseapi/gamelog.go new file mode 100644 index 0000000..a839753 --- /dev/null +++ b/server/analyseapi/gamelog.go @@ -0,0 +1,48 @@ +package main + +import ( + "q5" + "f5" +) + +type GameLog struct { + +} + +func (this *GameLog) Init() *GameLog { + f5.TgLog().SetPolyLog(true) + return this +} + +func (this *GameLog) UnInit() { +} + +func (this *GameLog) PlayerOnline(remoteAddr string, accountId string, registerTime int64) { + gameId := f5.ExtractGameIdFromAccountId(accountId) + channel := f5.ExtractChannelFromAccountId(accountId) + + prop := q5.NewMxoObject() + prop.SetXValue("channel", q5.NewXInt32(channel)) + prop.SetXValue("ad_channel", q5.NewXString("")) + prop.SetXValue("account_register_date", q5.NewXString(q5.FormatUnixDateTime(registerTime))) + prop.SetXValue("gameid", q5.NewXInt32(gameId)) + + f5.TgLog().AddTrackLog(gameId, accountId, remoteAddr, 21, 1, prop.AsXObject()) +} + +func (this *GameLog) PlayerOffline(remoteAddr string, accountId string, registerTime int64, onlineTime int64) { + gameId := f5.ExtractGameIdFromAccountId(accountId) + channel := f5.ExtractChannelFromAccountId(accountId) + + prop := q5.NewMxoObject() + prop.SetXValue("channel", q5.NewXInt32(channel)) + prop.SetXValue("ad_channel", q5.NewXString("")) + prop.SetXValue("account_register_date", q5.NewXString(q5.FormatUnixDateTime(registerTime))) + prop.SetXValue("gameid", q5.NewXInt32(gameId)) + + prop.SetXValue("online_time", q5.NewXString(q5.FormatUnixDateTime(onlineTime))) + prop.SetXValue("online_duration", q5.NewXString( + q5.FormatUnixDateTime(f5.App.NowUnix() - onlineTime))) + + f5.TgLog().AddTrackLog(gameId, accountId, remoteAddr, 21, 2, prop.AsXObject()) +} diff --git a/server/analyseapi/go.mod b/server/analyseapi/go.mod index 632d09a..4a501ff 100644 --- a/server/analyseapi/go.mod +++ b/server/analyseapi/go.mod @@ -1,4 +1,4 @@ -module analyseapi +module statserver go 1.11 diff --git a/server/analyseapi/main.go b/server/analyseapi/main.go index 2938b2e..4575b2d 100644 --- a/server/analyseapi/main.go +++ b/server/analyseapi/main.go @@ -1,11 +1,6 @@ package main -import ( - //"f5" -) - func main() { - App = &App_{} App.Init() App.Run() App.UnInit() diff --git a/server/analyseapi/makefile b/server/analyseapi/makefile index 0cbfb16..63d6a58 100644 --- a/server/analyseapi/makefile +++ b/server/analyseapi/makefile @@ -1,11 +1,20 @@ + compile: @. /etc/profile protoc --proto_path=../tools/protobuild --go_out=./mt ../tools/protobuild/mt.proto @export GOPROXY=https://goproxy.io - @go build -gcflags=all="-N -l" -o ../bin/analyseapi + @go build -gcflags=all="-N -l" -o ../bin/statserver + @echo "compile done" + +debug: + @. /etc/profile + + protoc --proto_path=../tools/protobuild --go_out=./mt ../tools/protobuild/mt.proto + @export GOPROXY=https://goproxy.io + @go build -gcflags=all="-N -l" -ldflags "-X q5.optDebug=1" -o ../bin/statserver @echo "compile done" clean: - @rm -f ../bin/analyseapi + @rm -f ../bin/statserver @echo "clean done" diff --git a/server/analyseapi/metamgr.go b/server/analyseapi/metamgr.go index c299e60..116472b 100644 --- a/server/analyseapi/metamgr.go +++ b/server/analyseapi/metamgr.go @@ -2,29 +2,39 @@ package main import "f5" import "mt" -//import "fmt" -//import "reflect" const ( MT_SERVER_INFO = 0 - MT_MAX + MT_CONF = iota + MT_MAX = iota ) type MetaMgr struct { f5.MetaMgr } -func (this *MetaMgr) Init() { +func (this *MetaMgr) Init() *MetaMgr { this.MetaMgr.Init() + configDir := "../config/" + if !f5.IsOnlineEnv() { + configDir = "/var/data/conf_test/statserver/" + } metaClasses := &[]f5.MetaClass{ f5.MetaClass{ PrimKey: "InstanceId", - FileName: "/var/data/conf_test/mail/mail.cluster.json", + FileName: configDir + "statserver.cluster.json", Idx: MT_SERVER_INFO, RawMeta: (*mt.ServerInfoMetas)(nil), WrapMeta: (*MtwServerInfo)(nil)}, + f5.MetaClass{ + FileName: configDir + "statserver.json", + Idx: MT_CONF, + RawMeta: (*mt.ConfMetas)(nil), + WrapMeta: (*MtwConf)(nil)}, } this.MetaMgr.RegisterMetaClasses(metaClasses) + this.Load() + return this } func (this *MetaMgr) UnInit() { @@ -40,8 +50,8 @@ func (this *MetaMgr) GetServer(instance_id int32) *MtwServerInfo { } } -func (this *MetaMgr) GetServerList() []*MtwServerInfo { - v, ok := this.MetaMgr.GetMetaList(MT_SERVER_INFO).([]*MtwServerInfo) +func (this *MetaMgr) GetConf() *MtwConf { + v, ok := this.MetaMgr.GetMetaById(MT_CONF, 1).(*MtwConf) if ok { return v } else { diff --git a/server/analyseapi/metawrap.go b/server/analyseapi/metawrap.go index e67f656..a62955a 100644 --- a/server/analyseapi/metawrap.go +++ b/server/analyseapi/metawrap.go @@ -5,3 +5,23 @@ import "mt" type MtwServerInfo struct { *mt.ServerInfo } + +type MtwConf struct { + *mt.Conf + hearbeatHash map[int32]int32 +} + +func (this *MtwConf) Init() { + this.hearbeatHash = make(map[int32]int32) + for _, v := range this.GetGameHeartbeat() { + this.hearbeatHash[v.GetGameid()] = v.GetHeartbeat() + } +} + +func (this *MtwConf) GetHeartBeatTimeout(gameid int32) int32 { + if time, ok := this.hearbeatHash[gameid]; ok { + return (time + this.GetNetDelay()) * 1000 + } else { + return (60 * 5 + this.GetNetDelay()) * 1000 + } +} diff --git a/server/analyseapi/statmgr.go b/server/analyseapi/statmgr.go new file mode 100644 index 0000000..bffdeb6 --- /dev/null +++ b/server/analyseapi/statmgr.go @@ -0,0 +1,164 @@ +package main + +import ( + "net/http" + "sync" + "fmt" + "q5" + "f5" +) + +type OnlineUser struct { + accountId string + sessionId string + timer *q5.TimerList +} + +type StatMgr struct { + onlineUserHash map[string]*OnlineUser + + onlineNumHash map[int64]int32 + onlineNumMutex sync.RWMutex +} + +func (this *StatMgr) Init() *StatMgr { + this.onlineUserHash = make(map[string]*OnlineUser) + this.onlineNumHash = make(map[int64]int32) + + f5.App.RegisterIMMsgHandle(IM_UPDATE_SESSION, this._IMUpdateSession) + G.HttpServer.RegisterHandle("Stat", "updateSession", this.__statUpdateSession) + G.HttpServer.RegisterHandle("Stat", "getRealTimeOnline", this.__statGetRealTimeOnline) + + return this +} + +func (this *StatMgr) UnInit() { + +} + +func (this *StatMgr) _IMUpdateSession(msgId int16, params* q5.XParams) { + /*if q5.Debug() { + f5.SysLog().Info("StatMgr._IMUpdateSession") + }*/ + accountId := params.Sender.GetString() + sessionId := params.Param1.GetString() + remoteAddr := params.Param2.GetString() + tryCount := params.Param3.GetInt32() + if tryCount > 0 { + return + } + instanceId := this.allocInstanceId(accountId) + if instanceId == f5.App.GetInstanceId() { + userInfo, ok := this.onlineUserHash[accountId] + if !ok { + this.playerOnline(remoteAddr, accountId, sessionId) + } else { + if userInfo.sessionId != sessionId { + if !f5.IsValidSessionId(accountId, sessionId, SESSION_KEY) { + f5.SysLog().Warning("invalid sessionid1 %s %s %s", + remoteAddr, + accountId, + sessionId) + return + } + userInfo.sessionId = sessionId + } + gameId := f5.ExtractGameIdFromAccountId(accountId) + f5.Timer().ModifyTimer( + userInfo.timer, + G.MetaMgr.GetConf().GetHeartBeatTimeout(gameId)) + } + } +} + +func (this *StatMgr) GetRealTimeOnline(gameId int32, channel int32) int32 { + this.onlineNumMutex.Lock() + defer this.onlineNumMutex.Unlock() + if v, ok := this.onlineNumHash[q5.MkInt64(gameId, channel)]; ok { + return v + } else { + return 0 + } +} + +func (this *StatMgr) incGameChannelOnline(gameId int32, channel int32) { + this.onlineNumMutex.Lock() + defer this.onlineNumMutex.Unlock() + this.onlineNumHash[q5.MkInt64(gameId, channel)] += 1 + this.onlineNumHash[q5.MkInt64(gameId, 0)] += 1 +} + +func (this *StatMgr) decGameChannelOnline(gameId int32, channel int32) { + this.onlineNumMutex.Lock() + defer this.onlineNumMutex.Unlock() + this.onlineNumHash[q5.MkInt64(gameId, channel)] -= 1 + this.onlineNumHash[q5.MkInt64(gameId, 0)] -= 1 +} + +func (this *StatMgr) allocInstanceId(accountId string) uint32 { + return 1 + //return q5.Crc32(accountId) +} + +func (this *StatMgr) playerOnline(remoteAddr string, accountId string, sessionId string) { + if q5.Debug() { + f5.SysLog().Info("playerOnline %s %s %s", + remoteAddr, + accountId, + sessionId) + } + if !f5.IsValidSessionId(accountId, sessionId, SESSION_KEY) { + f5.SysLog().Warning("invalid sessionid2 %s %s %s", + remoteAddr, + accountId, + sessionId) + return + } + gameId := f5.ExtractGameIdFromAccountId(accountId) + channel := f5.ExtractChannelFromAccountId(accountId) + registerTime := f5.ExtractRegisterTimeFromSessionId(sessionId) + userInfo := new(OnlineUser) + userInfo.timer = f5.Timer().AddDeadLineTimer( + G.MetaMgr.GetConf().GetHeartBeatTimeout(gameId), + func (params *q5.XParams) { + params.Sender.SetString("") + params.Param1.SetString(accountId) + params.Param3.SetInt32(registerTime) + }, + func (params *q5.XParams) { + this.playerOffline(remoteAddr, accountId, registerTime) + }) + this.onlineUserHash[accountId] = userInfo + this.incGameChannelOnline(gameId, channel) + G.GameLog.PlayerOnline(remoteAddr, accountId, int64(registerTime)) +} + +func (this *StatMgr) playerOffline(remoteAddr string, accountId string, registerTime int32) { + if q5.Debug() { + f5.SysLog().Info("playerOffline %s %s", + remoteAddr, + accountId) + } + gameId := f5.ExtractGameIdFromAccountId(accountId) + channel := f5.ExtractChannelFromAccountId(accountId) + delete(this.onlineUserHash, accountId) + this.decGameChannelOnline(gameId, channel) + G.GameLog.PlayerOffline(remoteAddr, accountId, int64(registerTime), 0) +} + +func (this *StatMgr) __statUpdateSession(w http.ResponseWriter,r *http.Request) { + f5.App.AddIMMsg(IM_UPDATE_SESSION, new(q5.XParams).Init(func (params *q5.XParams){ + params.Sender.SetString(q5.Request(r, "account_id").GetString()) + params.Param1.SetString(q5.Request(r, "session_id").GetString()) + params.Param2.SetString(q5.GetRequestRemoteAddr(r)) + params.Param3.SetString(q5.Request(r, "_try_count").GetString()) + })) + w.Write([]byte(`{"errcode":0, "errmsg":""}`)) +} + +func (this *StatMgr) __statGetRealTimeOnline(w http.ResponseWriter,r *http.Request) { + onlineNum := G.StatMgr.GetRealTimeOnline( + q5.Request(r, "game_id").GetInt32(), + q5.Request(r, "channel").GetInt32()) + w.Write([]byte(fmt.Sprintf(`{"errcode":0, "errmsg":"", "num":%d}`, onlineNum))) +}