优化结构,移除userGate类

This commit is contained in:
liuxiaobo 2025-05-27 19:14:43 +08:00
parent fb7d528825
commit f96715acdf
6 changed files with 73 additions and 97 deletions

View File

@ -3,6 +3,6 @@ package topicName
const (
//extTopic = ".topic"
//extGroup = ".group"
UserLogin = "user.login.topic"
UserOnline = "user.online.topic"
UserOffline = "user.offline.topic"
)

View File

@ -38,8 +38,8 @@ func (m *UserBindService) makeRedisKey(userId int64, typeId pb.ServiceTypeId) st
return fmt.Sprintf("%s_%d:%d", prefix, userId, int(typeId))
}
// 从redis中加载玩家曾经访问过的服务节点
func (m *UserBindService) loadFromRedis(userId int64, typeId pb.ServiceTypeId) string {
// 从redis中加载玩家曾经访问过的服务节点
func (m *UserBindService) LoadFromRedis(userId int64, typeId pb.ServiceTypeId) string {
k := m.makeRedisKey(userId, typeId)
if sName, err := m.rdb.Get(context.Background(), k).Result(); err != nil {
log.Error(err.Error())
@ -101,7 +101,7 @@ func (m *UserBindService) RandServiceNode(typeId pb.ServiceTypeId) (*etcd.Servic
// 根据服务类型,路由到对应的服务节点
func (m *UserBindService) FindServiceName(userId int64, typeId pb.ServiceTypeId) (string, error) {
// 内存中没有向redis中查询。redis中保留的服务节点不一定是可用的还需要向etcd中验证
if sName := m.loadFromRedis(userId, typeId); sName != "" && m.serviceIsValid(sName) {
if sName := m.LoadFromRedis(userId, typeId); sName != "" && m.serviceIsValid(sName) {
return sName, nil
}
// redis也没有玩家的服务节点信息从etcd中找可用服务节点随机选择一个

View File

@ -1,45 +1,38 @@
package model
import (
"context"
"encoding/json"
"fmt"
"game/common/utils"
"github.com/go-redis/redis/v8"
"time"
)
// 该类将玩家与网关绑定以及保存token这些事情混在一起了绑定关系由userBindService提供。token这些由login服提供
type UserGate struct {
GateName string `json:"gate_name"`
Token string `json:"token"`
OnlineTime utils.Time `json:"online"`
rdb *redis.Client
}
func NewUserGate() *UserGate {
return &UserGate{rdb: UserRedis}
}
func (u *UserGate) key(userId int64, gateId string) string {
return fmt.Sprintf("gateway:%v:%v", gateId, userId)
}
func (u *UserGate) Set(userId int64, gateId string, token string) {
u.GateName = gateId
u.Token = token
u.OnlineTime = utils.Time(time.Now())
u.rdb.Set(context.Background(), u.key(userId, gateId), utils.Marshal(u), time.Hour*24)
}
func (u *UserGate) Get(userId int64, gateId string) (*UserGate, error) {
s, err := u.rdb.Get(context.Background(), u.key(userId, gateId)).Result()
if err != nil {
return u, err
}
err = json.Unmarshal([]byte(s), u)
return u, err
}
func (u *UserGate) Del(userId int64, gateId string) {
_, _ = u.rdb.Del(context.Background(), u.key(userId, gateId)).Result()
}
//type UserGate struct {
// GateName string `json:"gate_name"`
// Token string `json:"token"`
// OnlineTime utils.Time `json:"online"`
// rdb *redis.Client
//}
//
//func NewUserGate() *UserGate {
// return &UserGate{rdb: UserRedis}
//}
//
//func (u *UserGate) key(userId int64, gateId string) string {
// return fmt.Sprintf("gateway:%v:%v", gateId, userId)
//}
//
//func (u *UserGate) Set(userId int64, gateId string, token string) {
// u.GateName = gateId
// u.Token = token
// u.OnlineTime = utils.Time(time.Now())
// u.rdb.Set(context.Background(), u.key(userId, gateId), utils.Marshal(u), time.Hour*24)
//}
//
//func (u *UserGate) Get(userId int64, gateId string) (*UserGate, error) {
// s, err := u.rdb.Get(context.Background(), u.key(userId, gateId)).Result()
// if err != nil {
// return u, err
// }
// err = json.Unmarshal([]byte(s), u)
// return u, err
//}
//
//func (u *UserGate) Del(userId int64, gateId string) {
// _, _ = u.rdb.Del(context.Background(), u.key(userId, gateId)).Result()
//}

View File

@ -1,29 +1,22 @@
package model
import (
"game/common/testHelper"
"game/common/utils"
"github.com/fox/fox/db"
"testing"
)
const (
userId = 1111
gateId = "gate-1"
token = "token"
)
func TestUserGate(t *testing.T) {
UserRedis, err = db.InitRedis(testHelper.RedisPassword, testHelper.Host, testHelper.RedisPort, 0)
if err != nil {
t.Fatal(err)
}
var ug *UserGate
ug, err = NewUserGate().Get(userId, gateId)
if err != nil {
t.Log(err)
ug.Set(userId, gateId, token)
ug, _ = NewUserGate().Get(userId, gateId)
}
t.Logf("user_gate:%v", utils.Marshal(ug))
}
//const (
// userId = 1111
// gateId = "gate-1"
// token = "token"
//)
//
//func TestUserGate(t *testing.T) {
// UserRedis, err = db.InitRedis(testHelper.RedisPassword, testHelper.Host, testHelper.RedisPort, 0)
// if err != nil {
// t.Fatal(err)
// }
// var ug *UserGate
// ug, err = NewUserGate().Get(userId, gateId)
// if err != nil {
// t.Log(err)
// ug.Set(userId, gateId, token)
// ug, _ = NewUserGate().Get(userId, gateId)
// }
// t.Logf("user_gate:%v", utils.Marshal(ug))
//}

View File

@ -2,7 +2,7 @@ package server
import (
"game/common/proto/pb"
"game/server/gate/model"
"game/common/topicName"
"github.com/fox/fox/processor"
"github.com/fox/fox/service"
"github.com/fox/fox/ws"
@ -26,25 +26,20 @@ func (s *GateService) onNtfUserOnline(conn ws.IConn, _ *pb.NtfUserOnlineMsg) {
// 收到登陆成功消息,判断是否顶号
func (s *GateService) onUserLogin(conn ws.IConn, msg *pb.S2CUserLoginMsg) {
defer func() {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogin), msg)
}()
// 登陆失败,回传玩家
if msg.Code != pb.ErrCode_EC_OK {
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogin), msg)
return
}
s.SendClientMsg(conn, int32(pb.LoginMsgId_S2CUserLogin), msg)
s.wss.SetUserId(conn.Id(), msg.UserId)
ug, _ := model.NewUserGate().Get(conn.UserId(), s.Name())
if ug == nil {
model.NewUserGate().Set(conn.UserId(), s.Name(), msg.Token)
return
}
sName := s.bindService.LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
// 网关不同,说明玩家在其它网关上登陆,
if ug.GateName != s.Name() {
s.SendServiceMsg(service.TopicEx(ug.GateName), conn, int32(pb.LoginMsgId_S2CUserLogout), &pb.S2CUserLogoutMsg{Code: pb.ErrCode_EC_LoginDiffLoc})
if sName != "" && sName != s.Name() {
s.SendServiceMsg(service.TopicEx(sName), conn, int32(pb.LoginMsgId_S2CUserLogout), &pb.S2CUserLogoutMsg{Code: pb.ErrCode_EC_LoginDiffLoc})
}
//conn.NotifyClose()
// 广播玩家上线
s.SendServiceMsg(topicName.UserOnline, conn, int32(pb.LoginMsgId_NtfUserOnline), &pb.NtfUserOnlineMsg{UserId: msg.UserId})
}
// 收到登出消息

View File

@ -195,18 +195,13 @@ func (s *GateService) SendClientMsg(conn ws.IConn, msgId int32, msg proto.Messag
func (s *GateService) WsOnDisconnect(conn ws.IConn) {
if conn.UserId() > 0 {
s.bindService.DelUserService(conn.UserId(), pb.ServiceTypeId_STI_Gate)
ug, err := model.NewUserGate().Get(conn.UserId(), s.Name())
if err != nil {
log.Error(err.Error())
} else {
sName := s.bindService.LoadFromRedis(conn.UserId(), pb.ServiceTypeId_STI_Gate)
// 相同网关则为正常下线删除redis信息然后向内网广播下线
// 不同网关,异地登陆顶号 由其它网关通知本网关向玩家发送下线消息(processor中处理),并主动关闭连接,不广播下线消息
if ug.GateName == s.Name() {
model.NewUserGate().Del(conn.UserId(), s.Name())
// 不同网关,异地登陆顶号 由其它网关通知本网关向玩家发送顶号消息(processor中处理),并主动关闭连接,不广播下线消息
if sName == s.Name() {
s.bindService.DelUserService(conn.UserId(), pb.ServiceTypeId_STI_Gate)
s.SendServiceMsg(topicName.UserOffline, conn, int32(pb.LoginMsgId_NtfUserOffline), &pb.NtfUserOfflineMsg{UserId: conn.UserId()})
}
}
log.Debug(s.Log("user:%v disconnect", conn.UserId()))
}
}