/* Sog 游戏基础库 2016 by zouwei */ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Sog; using Sog.Gate; namespace Gate { // 客户端连接的路由策略,可定制一定路由规则 public class ServerRoute : BaseReloadableService { private ServerApp m_app; private long m_selectBackEndSeq = 0; //接口实现 public override int GetServiceType() { return GateServiceType.ServerRoute; } //接口实现 public override void Dispose() { m_app = null; } public ServerRoute(ServerApp app) { m_app = app; } /// /// 选择后端逻辑服务器 /// /// /// public uint SelectBackEndServerID(GateClientInfo info) { //如果之前已经有了,直接采用 if(info.LinkServerID != 0) { return info.LinkServerID; } //随机选一个 int backEndType = GateServerUtils.GetServerConfig().backEndServerType; uint[] serverIDs = m_app.GetCluster().GetRemoteAppID(backEndType); if(serverIDs.Length == 0) { TraceLog.Error("ServerRoute.SelectBackEndServerID no valid logic server id, serverType {0}", backEndType); return 0; } uint serverId = 0; int myType = ServerIDUtils.GetServerType(m_app.ServerID); int myInstId = (int)ServerIDUtils.GetInstanceID(m_app.ServerID); //游戏服务器尽量选instid相同的,这样保证第一次选择就是正确的game,不用切 if (myType == (int)ServerType.GameGate && myInstId <= serverIDs.Length) { serverId = serverIDs[myInstId - 1]; } else { int index = (int)(m_selectBackEndSeq % serverIDs.Length); serverId = serverIDs[index]; m_selectBackEndSeq++; } TraceLog.Trace("SelectBackEndServerID SelectPlayerGameGate myInstId {0} serverId {1}", myInstId, ServerIDUtils.IDToString(serverId)); info.LinkServerID = serverId; return info.LinkServerID; } public void RouteBackEndServer(uint remoteAppID, MessageData message, GateMsgHeader header) { GateClientInfo info = GateServerUtils.GetGateClientService().GetGateClientInfoThreadSafe(header.SessionID); if (info == null) { TraceLog.Debug("ServerRoute.RouteBackEndServer session {0} message ,but can not find session,drop msg" , header.SessionID); return; } if (info.State != GameClientState.Noraml) { TraceLog.Debug("ServerRoute.RouteBackEndServer session {0} message ,but session stat is {1},drop msg" , header.SessionID, GameClientState.Noraml); return; } uint routeServerID = message.Header.ServerID; TraceLog.Debug("ServerRoute.RouteBackEndServer session {0} src server {1} change to dst server {2}" , header.SessionID, ServerIDUtils.IDToString(remoteAppID), ServerIDUtils.IDToString(routeServerID)); //判断下route的目标服务器合不合法 int backEndType = GateServerUtils.GetServerConfig().backEndServerType; uint[] serverIDs = m_app.GetCluster().GetRemoteAppID(backEndType); bool valid = false; foreach (uint serverId in serverIDs) { if (serverId == routeServerID) { valid = true; break; } } if (valid == false) { TraceLog.Error("ServerRoute.RouteBackEndServer session {0} message ,but route serverid invalid {1}" , header.SessionID, routeServerID); return; } //改后端服务器地址 info.LinkServerID = routeServerID; string ip = "0.0.0.0"; if (info.Session != null && info.Session.RemoteEndPoint != null) { try { ip = info.Session.RemoteEndPoint.ToString().Split(':')[0]; } catch (Exception) { } } //先通知一个connected GateClientConnectedReq req = new GateClientConnectedReq(); req.IPAddress = ip; GateServerUtils.GetServerMsgTrans().NotifyServerClientConnected(info, req); //转发消息,判断一下是不是有实际消息需要转发,没有就算了 if (message.Header.Length > GateMsgHeaderPacker.GetLength()) { TraceLog.Debug("ServerRoute.RouteBackEndServer session {0} trans route msg to new server" , header.SessionID); //这里面本来是GateMsgOpCode.Route,直接改成Trans就可以了 GateMsgHeaderPacker.RawSetGateMsgHeadOpCode(message.Buffer.Data, GateMsgOpCode.Trans); //拷贝一个新的,要不然内存管理会出问题 MessageData newMessage = new MessageData(); newMessage.Header = message.Header; newMessage.MallocData(message.Buffer.Length); Buffer.BlockCopy(message.Buffer.Data, 0, newMessage.Buffer.Data, 0, newMessage.Buffer.Length); m_app.GetCluster().Send(info.LinkServerID, newMessage); } } } }