message SSPlayerOnlineNtf{ //project social|fruit
message SSPlayerOfflineNtf{ //project social|battleboss|fruit
buildproto.bat
406 lines
10 KiB
Go
406 lines
10 KiB
Go
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_FRUIT = 16
|
||
SERVICE_NODE_TYPE_FRUIT_STR = "fruit"
|
||
|
||
//跨服使用
|
||
//局部跨服(部分服务器跨服)
|
||
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 ""
|
||
}
|