fatiao 9c39586fbb 为fruit增加一个服务消息
message SSPlayerOnlineNtf{  //project social|fruit
message SSPlayerOfflineNtf{ //project social|battleboss|fruit
buildproto.bat
2025-06-09 11:19:43 +08:00

406 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ""
}