diff --git a/bin/gamesapi/config/config.json b/bin/gamesapi/config/config.json index 7bf05787..062ee28b 100644 --- a/bin/gamesapi/config/config.json +++ b/bin/gamesapi/config/config.json @@ -1,6 +1,6 @@ { "gamesapi_url": "https://game2006sapi-test.kingsome.cn", "redirect_url": "https://game2006api-test.kingsome.cn", - "max_request_cache": 10, + "max_concurrent_num": 10, "request_over_time": 30 } diff --git a/server/gamesapi/app/app.go b/server/gamesapi/app/app.go index 3c3f7a84..179d432c 100644 --- a/server/gamesapi/app/app.go +++ b/server/gamesapi/app/app.go @@ -3,7 +3,6 @@ package app import ( "f5" //. "main/global" - "main/middleware" "mt" ) @@ -30,7 +29,6 @@ func (this *app) Init() { f5.LoadMetaTable(mt.Table) this.registerDataSources() this.initCb() - f5.GetApp().GetGinEngine().Use(middleware.CaCheck) } func (this *app) UnInit() { diff --git a/server/gamesapi/common/types.go b/server/gamesapi/common/types.go index 15f0eeb6..e8696e44 100644 --- a/server/gamesapi/common/types.go +++ b/server/gamesapi/common/types.go @@ -6,3 +6,6 @@ type App interface { type RouterGroup interface { } + +type ServiceMgr interface { +} diff --git a/server/gamesapi/constant/constant.go b/server/gamesapi/constant/constant.go index 1c284727..c8140346 100644 --- a/server/gamesapi/constant/constant.go +++ b/server/gamesapi/constant/constant.go @@ -1,12 +1,9 @@ package constant -const ( - MAIL_DB = "maildb" -) - const ( APP_MODULE_IDX = iota ROUTER_MODULE_IDX CONTROLLER_MGR_MODULE_IDX + SERVICE_MGR_MODULE_IDX MAX_MODULE_IDX ) diff --git a/server/gamesapi/global/global.go b/server/gamesapi/global/global.go index 5f713443..8fe71005 100644 --- a/server/gamesapi/global/global.go +++ b/server/gamesapi/global/global.go @@ -9,15 +9,21 @@ import ( var modules [constant.MAX_MODULE_IDX]q5.Module var initOrders = []int32{ + constant.SERVICE_MGR_MODULE_IDX, constant.ROUTER_MODULE_IDX, } var app common.App +var serviceMgr common.ServiceMgr func GetApp() common.App { return app } +func GetServiceMgr() common.ServiceMgr { + return serviceMgr +} + func RegModule(idx int32, m q5.Module) { fmt.Printf("RegModule module %d\n", idx) modules[idx] = m @@ -26,10 +32,11 @@ func RegModule(idx int32, m q5.Module) { { app = m.(common.App) } - case constant.ROUTER_MODULE_IDX: + case constant.SERVICE_MGR_MODULE_IDX: { - + serviceMgr = m.(common.ServiceMgr) } + case constant.ROUTER_MODULE_IDX: default: { panic("unknow module") diff --git a/server/gamesapi/initialize/enter.go b/server/gamesapi/initialize/enter.go index de86a7d6..04ac6528 100644 --- a/server/gamesapi/initialize/enter.go +++ b/server/gamesapi/initialize/enter.go @@ -5,6 +5,7 @@ import ( _ "main/controller" . "main/global" _ "main/router" + _ "main/service" ) func Init() { diff --git a/server/gamesapi/middleware/caauth.go b/server/gamesapi/middleware/caauth.go index 2e45647a..b851f0da 100644 --- a/server/gamesapi/middleware/caauth.go +++ b/server/gamesapi/middleware/caauth.go @@ -1,133 +1,4 @@ package middleware import ( - "f5" - "fmt" - "mt" - "net/http" - "q5" - "time" - - //. "main/global" - - "github.com/gin-gonic/gin" ) - -type RedirectInfo struct { - trace_id string - ori_req *gin.Context - sig string - sigtime int64 -} - -var requestCache = q5.ConcurrentMap[string, []*RedirectInfo]{} -var redirectRequest = q5.ConcurrentMap[string, *RedirectInfo]{} - -func CaCheck(c *gin.Context) { - accountId := c.DefaultQuery("account_id", "") - - if accountId == "" || !lockAccount(accountId) { - c.JSON(http.StatusOK, gin.H{ - "errcode": 1004, - "errmsg": "Too many requests", - }) - return - } - - emptyreq := false - - defer unlockAccount(accountId, emptyreq) - - cache, exist := requestCache.Load(accountId) - if !exist { - pcache := make([]*RedirectInfo, 0, mt.Table.Config.GetMaxCache()) - cache = &pcache - } - - info := new(RedirectInfo) - info.ori_req = c - info.sigtime = f5.GetApp().GetRealSeconds() - info.trace_id = fmt.Sprintf("%x%02x-%s", info.sigtime, len(*cache), accountId) - info.sig = q5.Md5Str(c.Request.URL.RawQuery + info.trace_id) - - if len(*cache) < int(mt.Table.Config.GetMaxCache()) { - *cache = append(*cache, info) - requestCache.Store(accountId, *cache) - unlockAccount(accountId, emptyreq) - - for { - time.Sleep(time.Millisecond * 100) - - if lockAccount(accountId) { - reqlist, _ := requestCache.Load(accountId) - if len(*reqlist) > 0 && (*reqlist)[0].trace_id == info.trace_id { - req := (*reqlist)[0] - (*reqlist) = (*reqlist)[1:] - - if req.sigtime+int64(mt.Table.Config.GetById(0).GetRequestOverTime()) > f5.GetApp().GetRealSeconds() { - redirectRequest.Store(accountId, req) - CaForward(req.ori_req, req.sig, req.trace_id) - redirectRequest.Delete(accountId) - } else { - req.ori_req.JSON(http.StatusOK, gin.H{ - "errcode": 1004, - "errmsg": "Too many players", - }) - } - - if len(*reqlist) > 0 { - requestCache.Store(accountId, *reqlist) - } else { - requestCache.Delete(accountId) - emptyreq = true - } - - return - } - - unlockAccount(accountId, emptyreq) - } - } - } else { - c.JSON(http.StatusOK, gin.H{ - "errcode": 1004, - "errmsg": "Too many requests", - }) - } -} - -func VerifySig(c *gin.Context) { - accountId := c.DefaultQuery("account_id", "") - traceId := c.DefaultQuery("trace_id", "") - sig := c.DefaultQuery("sig", "") - - if accountId == "" || traceId == "" || sig == "" { - c.JSON(http.StatusOK, gin.H{ - "errcode": 1002, - "errmsg": "empty params", - }) - return - } - - failresp := gin.H{ - "errcode": 1002, - "errmsg": "sig unavailable", - } - - req, exist := redirectRequest.Load(accountId) - if !exist { - c.JSON(http.StatusOK, failresp) - return - } - - if (*req).sig != sig || (*req).trace_id != traceId || - (*req).sigtime+int64(mt.Table.Config.GetById(0).GetRequestOverTime()) < f5.GetApp().GetRealSeconds() { - c.JSON(http.StatusOK, failresp) - return - } - - c.JSON(http.StatusOK, gin.H{ - "errcode": 0, - "errmsg": "", - }) -} diff --git a/server/gamesapi/middleware/caforward.go b/server/gamesapi/middleware/caforward.go index 4c5520eb..6c3ffad3 100644 --- a/server/gamesapi/middleware/caforward.go +++ b/server/gamesapi/middleware/caforward.go @@ -5,47 +5,108 @@ import ( "mt" "net/http" "q5" - + "main/service" + "jccommon" + "io/ioutil" + "bytes" + net_url "net/url" + "strings" + "errors" "github.com/gin-gonic/gin" ) -func CaForward(c *gin.Context, sig string, traceid string) { +func CaForward(c *gin.Context) { + accountId := c.DefaultQuery("account_id", "") + sessionId := c.DefaultQuery("session_id", "") - queryParams := c.Request.URL.Query() - params := map[string]string{} - for k, v := range queryParams { - params[k] = v[0] - } - if sig != "" { - params["sig"] = sig - params["trace_id"] = traceid + if !jccommon.IsValidSessionId(accountId, sessionId) { + f5.RspErr(c, 500, "invalid session_id") + c.Abort() + service.SApiForward.IncInvalidSessionTimes() + return } - fullrequrl := mt.Table.Config.GetById(0).GetRedirectUrl() + c.Request.URL.Path[5:] - cb := func(rsp f5.HttpCliResponse) { - if rsp.GetErr() != nil { - c.JSON(http.StatusOK, gin.H{ - "errcode": 1004, - "errmsg": rsp.GetErr(), - }) + cLock := service.SApiForward.AcquireLock(accountId) + defer service.SApiForward.ReleaseLock(cLock) + service.SApiForward.IncTotalTimes() + beginTick := q5.GetTickCount() + defer func() { + costTime := q5.GetTickCount() - beginTick + service.SApiForward.UpdateCostTime(costTime) + }() + newUrl := mt.Table.Config.GetById(0).GetRedirectUrl() + c.Request.URL.Path[5:] + if !q5.StrContains(newUrl, "?") { + newUrl = newUrl + "?" + } + { + u := net_url.Values{} + for k, v := range c.Request.URL.Query() { + u.Set(k, v[0]) + } + newUrl += u.Encode() + } + + var httpRequest *http.Request + var createErr error + switch strings.ToUpper(c.Request.Method) { + case "GET": { + service.SApiForward.IncGetTimes() + httpRequest, createErr = http.NewRequest("GET", newUrl, nil) + if !f5.IsOnlineEnv() { + f5.GetSysLog().Info("CaForward method:%s newUrl:%s ", c.Request.Method, newUrl) + } + } + case "POST": { + service.SApiForward.IncPostTimes() + if postData, err := c.GetRawData(); err == nil { + httpRequest, createErr = http.NewRequest("POST", newUrl, bytes.NewBuffer(postData)) + contentType := c.GetHeader("Content-Type") + if contentType != "" { + httpRequest.Header.Set("Content-Type", contentType) + } + if !f5.IsOnlineEnv() { + f5.GetSysLog().Info("CaForward method:%s newUrl:%s Content-Type:%s postData:%s", + c.Request.Method, + newUrl, + contentType, + postData) + } + } else { + createErr = err + } + } + default: { + createErr = errors.New("method error") + } + } + if createErr != nil { + service.SApiForward.IncCreateErrTimes() + f5.RspErr(c, 500, "create request error") + c.Abort() + f5.GetSysLog().Info("CaForward create request url:%s error:%s", newUrl, createErr) + return + } + client := &http.Client{} + if resp, err := client.Do(httpRequest); err == nil { + defer resp.Body.Close() + if bytes, err := ioutil.ReadAll(resp.Body); err == nil { + service.SApiForward.IncOkTimes() + c.String(200, string(bytes)) + c.Abort() + return + } else { + service.SApiForward.IncReadRspErrTimes() + f5.RspErr(c, 500, "read response error") + c.Abort() + f5.GetSysLog().Info("CaForward read response url:%s eror:%s", newUrl, err) return } - - c.String(http.StatusOK, rsp.GetRawData()) + } else { + service.SApiForward.IncDoErrTimes() + f5.RspErr(c, 500, "client.Do error") + c.Abort() + f5.GetSysLog().Info("CaForward client.Do url:%s error:%s", newUrl, err) + return } - switch c.Request.Method { - case "GET": - f5.GetHttpCliMgr().SendGoStyleRequest( - fullrequrl, - params, - cb) - case "POST": - f5.GetHttpCliMgr().SendGoStylePost( - fullrequrl, - params, - c.ContentType(), - q5.GetPostBody(c.Request), - cb) - } } diff --git a/server/gamesapi/middleware/calock.go b/server/gamesapi/middleware/calock.go deleted file mode 100644 index 908cd48a..00000000 --- a/server/gamesapi/middleware/calock.go +++ /dev/null @@ -1,27 +0,0 @@ -package middleware - -import ( - "q5" - "sync" -) - -var accountMutexmap q5.ConcurrentMap[string, *sync.Mutex] - -func lockAccount(account string) bool { - mutex, exist := accountMutexmap.Load(account) - if !exist { - tmp := new(sync.Mutex) - mutex = &tmp - } - return (*mutex).TryLock() -} - -func unlockAccount(account string, del bool) { - mutex, exist := accountMutexmap.Load(account) - if exist { - (*mutex).Unlock() - if del { - accountMutexmap.Delete(account) - } - } -} diff --git a/server/gamesapi/mt/Config.go b/server/gamesapi/mt/Config.go index 40dce32b..840186ab 100644 --- a/server/gamesapi/mt/Config.go +++ b/server/gamesapi/mt/Config.go @@ -20,15 +20,15 @@ func (this *ConfigTable) GetGameSApiUrl() string { func (this *ConfigTable) GetSecretKey() string { return this.selfConf.GetSecretKey() - } + +func (this *ConfigTable) GetMaxConcurrentNum() int32 { + return this.selfConf.GetMaxConcurrentNum() +} + func (this *ConfigTable) PostInit1() { this.selfConf = this.GetById(int64(0)) if this.selfConf == nil { panic("gamesapi config无法读取本服配置") } } - -func (this *ConfigTable) GetMaxCache() int32 { - return this.selfConf.GetMaxRequestCache() -} diff --git a/server/gamesapi/mtb/mtb.auto_gen.go b/server/gamesapi/mtb/mtb.auto_gen.go index 312d5ac6..1910015b 100644 --- a/server/gamesapi/mtb/mtb.auto_gen.go +++ b/server/gamesapi/mtb/mtb.auto_gen.go @@ -19,7 +19,7 @@ type Config struct { gm_open int32 gm_secret_key string redirect_url string - max_request_cache int32 + max_concurrent_num int32 request_over_time int32 _flags1_ uint64 @@ -90,11 +90,11 @@ func (this *Config) HasRedirectUrl() bool { return (this._flags1_ & (uint64(1) << 5)) > 0 } -func (this *Config) GetMaxRequestCache() int32 { - return this.max_request_cache +func (this *Config) GetMaxConcurrentNum() int32 { + return this.max_concurrent_num } -func (this *Config) HasMaxRequestCache() bool { +func (this *Config) HasMaxConcurrentNum() bool { return (this._flags1_ & (uint64(1) << 6)) > 0 } @@ -119,6 +119,6 @@ func (this *Config) LoadFromKv(kv map[string]interface{}) { f5.ReadMetaTableField(&this.gm_open, "gm_open", &this._flags1_, 3, kv) f5.ReadMetaTableField(&this.gm_secret_key, "gm_secret_key", &this._flags1_, 4, kv) f5.ReadMetaTableField(&this.redirect_url, "redirect_url", &this._flags1_, 5, kv) - f5.ReadMetaTableField(&this.max_request_cache, "max_request_cache", &this._flags1_, 6, kv) + f5.ReadMetaTableField(&this.max_concurrent_num, "max_concurrent_num", &this._flags1_, 6, kv) f5.ReadMetaTableField(&this.request_over_time, "request_over_time", &this._flags1_, 7, kv) } diff --git a/server/gamesapi/proto/mt.proto b/server/gamesapi/proto/mt.proto index 4929bc81..5b4f6a76 100644 --- a/server/gamesapi/proto/mt.proto +++ b/server/gamesapi/proto/mt.proto @@ -16,6 +16,6 @@ message Config optional int32 gm_open = 3; optional string gm_secret_key = 4; optional string redirect_url = 5; - optional int32 max_request_cache = 6; + optional int32 max_concurrent_num = 6; optional int32 request_over_time = 7; } diff --git a/server/gamesapi/router/routermgr.go b/server/gamesapi/router/routermgr.go index ab334f7c..7ab29e0f 100644 --- a/server/gamesapi/router/routermgr.go +++ b/server/gamesapi/router/routermgr.go @@ -13,8 +13,7 @@ type routerMgr struct { func (this *routerMgr) Init() { redirectGroup := f5.GetApp().GetGinEngine().Group("/sapi") - redirectGroup.Any("webapp/index.php?", middleware.CaCheck) - redirectGroup.Any("check", middleware.VerifySig) + redirectGroup.Any("webapp/index.php", middleware.CaForward) f5.GetSysLog().Info("routerMgr.init") } diff --git a/server/gamesapi/service/export.go b/server/gamesapi/service/export.go new file mode 100644 index 00000000..bbfe94fe --- /dev/null +++ b/server/gamesapi/service/export.go @@ -0,0 +1,13 @@ +package service + +import ( + "main/constant" + "main/global" +) + +var _serviceMgr = new(serviceMgr) +var SApiForward *sApiForward + +func init() { + global.RegModule(constant.SERVICE_MGR_MODULE_IDX, _serviceMgr) +} diff --git a/server/gamesapi/service/sapi_forward.go b/server/gamesapi/service/sapi_forward.go new file mode 100644 index 00000000..e8f8c299 --- /dev/null +++ b/server/gamesapi/service/sapi_forward.go @@ -0,0 +1,102 @@ +package service + +import ( + "q5" + "sync" + "mt" + "sync/atomic" +) + +type sApiForward struct { + userCache []*SApiForwardLockCache +} + +type SApiForwardLockCache struct { + lock *sync.Mutex + userHash *map[string]*SApiForwardLock +} + +type SApiForwardLock struct { + accountId string + lockTimes int32 + lock *sync.Mutex +} + +func (this *sApiForward) init() { + q5.NewSlice(&this.userCache, 1024, 1024) + for i := 0; i < len(this.userCache); i++ { + p := new(SApiForwardLockCache) + p.lock = new(sync.Mutex) + p.userHash = new(map[string]*SApiForwardLock) + this.userCache[i] = p + } +} + +func (this *sApiForward) unInit() { +} + +func (this *sApiForward) AcquireLock(accountId string) *SApiForwardLock { + crc32 := q5.Crc32(accountId) + c := this.userCache[int64(crc32) % int64(len(this.userCache))] + u := this.getOrCreate(c, accountId) + if atomic.AddInt32(&u.lockTimes, 1) > mt.Table.Config.GetMaxConcurrentNum() { + atomic.AddInt32(&u.lockTimes, -1) + return nil + } + u.lock.Lock() + return u +} + +func (this *sApiForward) ReleaseLock(l *SApiForwardLock) { + l.lock.Unlock() + atomic.AddInt32(&l.lockTimes, -1) +} + +func (this *sApiForward) IncInvalidSessionTimes() { + +} + +func (this *sApiForward) IncTotalTimes() { + +} + +func (this *sApiForward) IncGetTimes() { + +} + +func (this *sApiForward) IncPostTimes() { + +} + +func (this *sApiForward) IncCreateErrTimes() { + +} + +func (this *sApiForward) IncDoErrTimes() { + +} + +func (this *sApiForward) IncOkTimes() { + +} + +func (this *sApiForward) IncReadRspErrTimes() { + +} + +func (this *sApiForward) UpdateCostTime(costTime int64) { + +} + +func (this *sApiForward) getOrCreate(c *SApiForwardLockCache, accountId string) *SApiForwardLock { + c.lock.Lock() + defer c.lock.Unlock() + if u, ok := (*c.userHash)[accountId]; ok { + return u + } else { + u = new(SApiForwardLock) + u.accountId = accountId + u.lock = new(sync.Mutex) + return u + } +} diff --git a/server/gamesapi/service/servicemgr.go b/server/gamesapi/service/servicemgr.go new file mode 100644 index 00000000..24b21e32 --- /dev/null +++ b/server/gamesapi/service/servicemgr.go @@ -0,0 +1,13 @@ +package service + +type serviceMgr struct { +} + +func (this *serviceMgr) Init() { + SApiForward = new(sApiForward) + SApiForward.init() +} + +func (this *serviceMgr) UnInit() { + SApiForward.unInit() +} diff --git a/server/jccommon/utils.go b/server/jccommon/utils.go index c7052a51..8b966629 100644 --- a/server/jccommon/utils.go +++ b/server/jccommon/utils.go @@ -84,3 +84,7 @@ func CalcContributionScore(nfts []*NftStacking) float64 { score = baseScore * (1 + rate) return score } + +func IsValidSessionId(accountId string, sessionId string) bool { + return true +} diff --git a/server/marketserver/api/v1/event/event.go b/server/marketserver/api/v1/event/event.go index 48544a86..150c98fe 100644 --- a/server/marketserver/api/v1/event/event.go +++ b/server/marketserver/api/v1/event/event.go @@ -162,7 +162,7 @@ func (ea *EventApi) ActivityQuery(c *gin.Context) { func(ds *f5.DataSet) { p := new(common.NftDto) p.NetId = q5.ToInt32(ds.GetByName("net_id")) - p.ContractAddress = ds.GetByName("contract_address") + p.ContractAddress = ds.GetByName("nft_contract_address") p.TokenId = ds.GetByName("token_id") p.Payload = map[string]string{} p.Payload.(map[string]string)["type"] = ds.GetByName("event_name")