| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- package model
- import (
- "math/rand"
- "rocommon"
- "rocommon/service"
- "rocommon/util"
- "sync"
- )
- //远端服务器节点处理
- var (
- serviceNode sync.RWMutex
- //服务器节点之间的连接
- serviceConnBySID = map[string]rocommon.Session{}
- //跨服router节点使用
- serviceConnByZone = map[int][]string{} //[zone][sid...]
- //auth节点另外再存一份一份,提高效率
- authConnBySID = map[string]rocommon.Session{}
- dbSelectIndex = 0
- authSelectIndex = 0
- socialSelectIndex = 0
- gameSelectIndex = 0
- mapSelectIndex = 0
- bossSelectIndex = 0
- )
- //服务器节点类型枚举
- //服务器类型节点Type:[1 gate] [2 game] [3 db] [4 auth] [5 social chat mail] [10 map] [11 map router] [12 pev] [13 boss]
- //20 crossrouter跨服路由 21crossserver跨服玩家节点
- const (
- SERVICE_NODE_TYPE_GATE = 1
- SERVICE_NODE_TYPE_GATE_STR = "gate"
- SERVICE_NODE_TYPE_GAME = 2
- SERVICE_NODE_TYPE_GAME_STR = "game"
- SERVICE_NODE_TYPE_DB = 3
- SERVICE_NODE_TYPE_DB_STR = "db"
- SERVICE_NODE_TYPE_AUTH = 4
- SERVICE_NODE_TYPE_AUTH_STR = "auth"
- SERVICE_NODE_TYPE_SOCIAL = 5
- SERVICE_NODE_TYPE_SOCIAL_STR = "social"
- SERVICE_NODE_TYPE_RANK = 6
- SERVICE_NODE_TYPE_RANK_STR = "rank"
- SERVICE_NODE_TYPE_GUILD = 7
- SERVICE_NODE_TYPE_GUILD_STR = "guild"
- SERVICE_NODE_TYPE_AOI = 10
- SERVICE_NODE_TYPE_AOI_STR = "aoi"
- SERVICE_NODE_TYPE_MAP_ROUTER = 11
- SERVICE_NODE_TYPE_MAP_ROUTER_STR = "maprouter"
- SERVICE_NODE_TYPE_PVE = 12
- SERVICE_NODE_TYPE_PVE_STR = "pve"
- SERVICE_NODE_TYPE_BOSS = 13
- SERVICE_NODE_TYPE_BOSS_STR = "battleboss"
- SERVICE_NODE_TYPE_WEBGM = 14
- SERVICE_NODE_TYPE_WEBGM_STR = "gmweb"
- SERVICE_NODE_TYPE_BATTLERECORD = 15
- SERVICE_NODE_TYPE_BATTLERECORD_STR = "battlerecord"
- //跨服使用
- //局部跨服(部分服务器跨服)
- SERVICE_NODE_TYPE_CROSSROUTER = 20
- SERVICE_NODE_TYPE_CROSSROUTER_STR = "crossrouter"
- SERVICE_NODE_TYPE_CROSSSERVER = 21
- SERVICE_NODE_TYPE_CROSSSERVER_STR = "crossserver" //跨服玩法(远航试炼)
- SERVICE_NODE_TYPE_CROSSRANK = 22
- SERVICE_NODE_TYPE_CROSSRANK_STR = "crossrank" //跨服排行榜
- //全局跨服使用(所有服务器跨服)
- SERVICE_NODE_TYPE_GLOBALCROSSROUTER = 30
- SERVICE_NODE_TYPE_GLOBALCROSSROUTER_STR = "gcrossrouter"
- SERVICE_NODE_TYPE_GLOBALCROSSMAP = 31
- SERVICE_NODE_TYPE_GLOBALCROSSMAP_STR = "gcrossmap"
- )
- //需要加锁处理(后续放到主线程队列中做处理)
- func AddServiceNode(session rocommon.Session, sid, name string, from string) {
- serviceNode.Lock()
- defer serviceNode.Unlock()
- serverType, zone, index, err := service.ParseServiceID(sid)
- if err == nil {
- session.(rocommon.ContextSet).SetContextData("ctx",
- &service.ETCDServiceDesc{
- ID: sid,
- Name: name,
- Type: serverType,
- Zone: zone,
- Index: index,
- }, "AddServiceNode")
- serviceConnBySID[sid] = session
- if serverType == SERVICE_NODE_TYPE_SOCIAL {
- serviceConnByZone[zone] = append(serviceConnByZone[zone], sid)
- } else if serverType == SERVICE_NODE_TYPE_AUTH {
- authConnBySID[sid] = session
- }
- util.InfoF("[AddServiceNode_%v] %v", from, sid)
- } else {
- util.WarnF("[AddServiceNode_%v] %v err:%v", from, sid, err)
- }
- }
- func RemoveServiceNode(session rocommon.Session) string {
- retSID := ""
- if session == nil {
- return retSID
- }
- ctx := Session2Context(session)
- if ctx != nil {
- serviceNode.Lock()
- delete(serviceConnBySID, ctx.ID)
- delete(authConnBySID, ctx.ID)
- zoneNodeList, ok := serviceConnByZone[ctx.Zone]
- if ok {
- for idx := 0; idx < len(zoneNodeList); idx++ {
- if zoneNodeList[idx] == ctx.ID {
- serviceConnByZone[ctx.Zone] =
- append(serviceConnByZone[ctx.Zone][:idx], serviceConnByZone[ctx.Zone][idx+1:]...)
- break
- }
- }
- }
- serviceNode.Unlock()
- if ctx.Type == SERVICE_NODE_TYPE_GATE {
- retSID = ctx.ID
- }
- retSID = ctx.ID
- util.InfoF("[RemoveServiceNode]service nod conn removed sessionId:%v sid:%v", session.ID(), ctx.ID)
- } else {
- util.InfoF("[RemoveServiceNode]service nod conn removed sessionId:%v", session.ID())
- }
- return retSID
- }
- func Session2Context(serviceSess rocommon.Session) *service.ETCDServiceDesc {
- if raw, ok := serviceSess.(rocommon.ContextSet).GetContextData("ctx"); ok {
- return raw.(*service.ETCDServiceDesc)
- }
- return nil
- }
- func RemoveServiceNodeByName(sid string) {
- if sid == "" {
- return
- }
- serviceNode.Lock()
- delete(serviceConnBySID, sid)
- _, zone, _, _ := service.ParseServiceID(sid)
- zoneNodeList, ok := serviceConnByZone[zone]
- if ok {
- for idx := 0; idx < len(zoneNodeList); idx++ {
- if zoneNodeList[idx] == sid {
- serviceConnByZone[zone] =
- append(serviceConnByZone[zone][:idx], serviceConnByZone[zone][idx+1:]...)
- break
- }
- }
- }
- delete(authConnBySID, sid)
- serviceNode.Unlock()
- }
- //给定sid获得和服务器节点连接的session
- func GetServiceNode(sid string) rocommon.Session {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- if sess, ok := serviceConnBySID[sid]; ok {
- return sess
- }
- return nil
- }
- //获取指定服务器的节点名称列表
- func GetAllServiceNodeByName(serviceName string) []string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- var serviceNodeList []string
- for _, node := range serviceConnBySID {
- if raw, ok := node.(rocommon.ContextSet).GetContextData("ctx"); ok {
- sid := raw.(*service.ETCDServiceDesc)
- if sid.Name == serviceName {
- serviceNodeList = append(serviceNodeList, sid.ID)
- }
- }
- }
- return serviceNodeList
- }
- //获取指定服务器的index列表
- func GetAllServiceNodeIdByName(serviceName string) []int32 {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- var serviceIdList []int32
- for _, node := range serviceConnBySID {
- if raw, ok := node.(rocommon.ContextSet).GetContextData("ctx"); ok {
- sid := raw.(*service.ETCDServiceDesc)
- if sid.Name == serviceName {
- serviceIdList = append(serviceIdList, int32(sid.Index))
- }
- }
- }
- return serviceIdList
- }
- func GetAllSocialServiceNodeByZone(zone int, serviceName string) []string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- if zoneNodeList, ok := serviceConnByZone[zone]; ok {
- return zoneNodeList
- }
- return nil
- }
- func GetAllZoneSocialServiceNode(serviceName string) []string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- var retNodeList []string
- for _, node := range serviceConnByZone {
- if len(node) > 0 {
- retNodeList = append(retNodeList, node[0])
- }
- }
- return retNodeList
- }
- //根据区组中的ID来获取对应服务器类型节点
- func GetServiceNodeById(serviceName string, id int) string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- for _, node := range serviceConnBySID {
- if raw, ok := node.(rocommon.ContextSet).GetContextData("ctx"); ok {
- sid := raw.(*service.ETCDServiceDesc)
- if sid.Name == serviceName && sid.Index == id {
- return sid.ID
- }
- }
- }
- return ""
- }
- func GetServiceNodeAndSession(serviceName string, serviceTypeName string, id uint64) (string, rocommon.Session) {
- if serviceName != "" {
- tmpSess := GetServiceNode(serviceName)
- if tmpSess == nil {
- RemoveServiceNodeByName(serviceName)
- } else {
- return serviceName, tmpSess
- }
- }
- tmpServiceName, tmpSess := SelectServiceNodeAndSession(serviceTypeName, id)
- if tmpServiceName != "" {
- return tmpServiceName, tmpSess
- } else {
- return "", nil
- }
- }
- func SelectServiceNodeAndSession(serviceName string, id uint64) (string, rocommon.Session) {
- serviceNode := SelectServiceNode(serviceName, id)
- if serviceNode == "" {
- return serviceNode, nil
- }
- serviceSess := GetServiceNode(serviceNode)
- if serviceSess == nil {
- RemoveServiceNodeByName(serviceNode)
- for {
- serviceNode = SelectServiceNode(serviceName, 0)
- if serviceNode == "" {
- break
- }
- serviceSess = GetServiceNode(serviceNode)
- if serviceSess == nil {
- RemoveServiceNodeByName(serviceNode)
- } else {
- break
- }
- }
- }
- return serviceNode, serviceSess
- }
- func SelectServiceNode(serviceName string, id uint64) string {
- if id == 0 {
- id = uint64(rand.Int31n(100))
- }
- switch serviceName {
- case SERVICE_NODE_TYPE_DB_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_AUTH_STR:
- return SelectAuthServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_SOCIAL_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_GAME_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_AOI_STR:
- return selectServiceNode(serviceName, id)
- //return selectAoiServiceNode(serviceName)
- case SERVICE_NODE_TYPE_MAP_ROUTER_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_BOSS_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_RANK_STR:
- return selectAoiServiceNode(serviceName)
- case SERVICE_NODE_TYPE_GUILD_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_BATTLERECORD_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_WEBGM_STR:
- return selectServiceNode(serviceName, id)
- case SERVICE_NODE_TYPE_CROSSROUTER_STR:
- return selectServiceNode(serviceName, id)
- }
- return ""
- }
- //id确定的某一个服务器节点
- func selectServiceNode(serviceName string, id uint64) string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- var retIDList []string
- for _, node := range serviceConnBySID {
- if raw, ok := node.(rocommon.ContextSet).GetContextData("ctx"); ok {
- sid := raw.(*service.ETCDServiceDesc)
- if sid.Name == serviceName {
- retIDList = append(retIDList, sid.ID)
- }
- }
- }
- if len(retIDList) <= 0 {
- return ""
- }
- modNum := int(id % uint64(len(retIDList)))
- return retIDList[modNum]
- }
- func SelectAuthServiceNode(serviceName string, sessionId uint64) string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- nodeLen := len(authConnBySID)
- if nodeLen <= 0 {
- return ""
- }
- selectIdx := int(sessionId % uint64(nodeLen))
- idx := 0
- for _, node := range authConnBySID {
- if idx == selectIdx {
- if raw, ok := node.(rocommon.ContextSet).GetContextData("ctx"); ok {
- sid := raw.(*service.ETCDServiceDesc)
- if sid.Name == serviceName {
- //需要通知服务器状态
- return sid.ID
- }
- }
- }
- idx++
- }
- return ""
- }
- //todo..
- // 选择负载较低的节点进入
- func selectAoiServiceNode(serviceName string) string {
- serviceNode.RLock()
- defer serviceNode.RUnlock()
- for _, node := range serviceConnBySID {
- if raw, ok := node.(rocommon.ContextSet).GetContextData("ctx"); ok {
- sid := raw.(*service.ETCDServiceDesc)
- if sid.Name == serviceName {
- //需要通知服务器状态
- return sid.ID
- }
- }
- }
- return ""
- }
|