服务器的配置分了三个文件:分别是ChannelConfig.xml、HotFixConfig.xml、ServerConfig.xml。
ChannelConfig.xml 标签中的属性
ChannelId: 渠道Id
InnerVersion: 内部版本号
SourceVersion: 该渠道当前的资源版本号(根据当前的资源版本号和资源地址拼接出一个绝对路径)
SourceUrl: 资源站点的Ip和端口
RechargeUrl: 充值服务器的地址
PayServerNo: 充值服务器编号
TDAppId: 统计平台编号
IsOpenTD: 是否开启统计
Xml配置
<?xml version="1.0" encoding="utf-8" ?> <Root> <Channel ChannelId="0" InnerVersion="1001" SourceVersion="1.0.7" SourceUrl="http://127.0.0.1:8090" RechargeUrl="http://127.0.0.1" PayServerNo="" TDAppId="" IsOpenTD="" /> </Root>
ChannelConfig.cs代码解析加载ChannelConfig.xml。使用了System.Xml.Linq的XDocument工具类来加载xml文件。其基本原理就是获取到Root节点下名为“Channel”的所有Element节点,然后使用迭代器循环,拿到每一个Element中的属性,先缓存ChannelEntity结构中,最后存到字典里。
namespace Servers.Common { public class ChannelConfig { public static Dictionary<string, ChannelEntity> m_dicChannel; //渠道数据初始化 public static void Init() { m_dicChannel = new Dictionary<string, ChannelEntity>(); string path = AppDomain.CurrentDomain.BaseDirectory + "Configs/ChannelConfig.xml"; ChannelEntity entity; XDocument doc = XDocument.Load(path); XElement item; IEnumerator<XElement> iter = doc.Root.Elements("Channel").GetEnumerator(); for (; iter.MoveNext();) { item = iter.Current; entity = new ChannelEntity(); int.TryParse(item.Attribute("ChannelId").Value,out entity.ChannelId); int.TryParse(item.Attribute("InnerVersion").Value,out entity.InnerVersion); entity.SourceVersion = item.Attribute("SourceVersion").Value; entity.SourceUrl = item.Attribute("SourceUrl").Value; entity.RechargeUrl = item.Attribute("RechargeUrl").Value; int.TryParse(item.Attribute("PayServerNo").Value, out entity.InnerVersion); entity.TDAppId = item.Attribute("TDAppId").Value; bool.TryParse(item.Attribute("IsOpenTD").Value,out entity.IsOpenTD); //频道Id_内部版本 m_dicChannel[entity.ChannelId + "_" + entity.InnerVersion] = entity; } Console.WriteLine(" ChannelConfig Load Complete"); } } }
HotFixConfig.xml中的属性
Key:Dll名字
Value:Dll文件名
Xml配置。热更新dll名称配置表格的原因是每次加载的时候都需要把名字往后+1,C#不允许加载相同名字的Dll
<?xml version="1.0" encoding="utf-8" ?> <Root> <Item Key="HotFixAssemblyName" Value="Servers.HotFix.dll"/> </Root>
HotFixConfig.cs代码解析加载HotFixConfig.xml。
using System; using System.Collections.Generic; using System.Text; using System.Xml.Linq; namespace Servers.Common { //可以热更新的配置文件 public class HotFixConfig { private static Dictionary<string, string> m_dicParams; //根据Key获取参数 public static string GetParams(string key) { string value = null; m_dicParams.TryGetValue(key,out value); return value; } //加载热更新dll参数 public static void Load() { //有可能会重复Load,所以每次Load需要Clear操作 if (null == m_dicParams) m_dicParams = new Dictionary<string, string>(); else m_dicParams.Clear(); //cs工程目录+Configs目录,拼接出来一个绝对目录 string path = AppDomain.CurrentDomain.BaseDirectory + "Configs/HotFixConfig.xml"; XElement item; XDocument doc = XDocument.Load(path); IEnumerator<XElement> iter = doc.Root.Elements("Item").GetEnumerator(); for (; iter.MoveNext();) { item = iter.Current; string key = item.Attribute("Key").Value; string value = item.Attribute("Value").Value; m_dicParams[key] = value; } Console.WriteLine(" HotFixConfig Load Complete"); } } }
ServerConfig.xml 标签中的属性
AreaServerId: 区服编号
CurrServerType: 当前服务器类型
CurrServerId: 当前服务器编号
MongoConnectString: MongoDB连接字符串
RedisConnectString: Redis连接字符串
DataTablePath: 数据表路径
Servers: 服务器配置
Xml配置,这个是按照单服的结构设计的xml,如果以后有多服了,得把Servers、DB、Redis都得移到AreaServer里面去,外面套一层结构
<?xml version="1.0" encoding="utf-8" ?> <Root> <AreaServerId>1</AreaServerId> <CurrServerType>0</CurrServerType> <CurrServerId>0</CurrServerId> <MongoConnectString>mongodb://127.0.0.1</MongoConnectString> <RedisConnectString>127.0.0.1:6379</RedisConnectString> <DataTablePath>C:\game\Server\Release\DataTable</DataTablePath> <Servers> <!--中心(世界)服务器-->> <Item ServerType="0" ServerId="1" Ip="10.0.24.10" Port="1301"/> <!--游戏服务器1-->> <Item ServerType="1" ServerId="1" Ip="10.0.24.10" Port="1302"/> <!--游戏服务器2-->> <Item ServerType="1" ServerId="2" Ip="10.0.24.10" Port="1303"/> <!--网关服务器1-->> <Item ServerType="2" ServerId="1" Ip="10.0.24.10" Port="1304"/> <!--网关服务器2-->> <Item ServerType="2" ServerId="2" Ip="10.0.24.10" Port="1305"/> </Servers> <Scenes> <!--这些json是啥?到时候写到寻路服务器的时候再看看吧!-->> <Item SceneId="1" ServerId="1" AOIJsonDataPath="" /> <Item SceneId="2" ServerId="1" AOIJsonDataPath="" /> <Item SceneId="3" ServerId="2" AOIJsonDataPath="" /> <Item SceneId="4" ServerId="2" AOIJsonDataPath="" /> <Item SceneId="5" ServerId="2" AOIJsonDataPath="" /> <Item SceneId="6" ServerId="2" AOIJsonDataPath="" /> <Item SceneId="7" ServerId="2" AOIJsonDataPath="" /> <Item SceneId="8" ServerId="2" AOIJsonDataPath="" /> </Scenes> </Root>
ServerConfig.cs代码解析加载ServerConfig.xml。SceneConfig结构存的是哪些服务器应该为哪些场景提供服务器的信息,一个服务器可能算量有限并不能为整个大区的提供计算,将场景为单位把玩家划分到了不同的服务器上进行计算。Server类存的是单个服务器的配置,这个服务器需要开启的场景列表信息。ServerConfig则是有点像是传统的Manager类,会记录所有的Server信息到map结构里。
using System; using System.Collections.Generic; using System.Text; using System.Xml.Linq; using Servers.Core; namespace Servers.Common { public class SceneConfig { //场景编号 public int SceneId; //服务器编号 public int ServerId; //AOI区域数据路径 public string AOIJsonDataPath; } //单台服务器配置 public class Server { //服务器类型 public ConstDefine.ServerType CurrServerType; //服务器编号 public int ServerId; //服务器Ip public string Ip; //服务器端口 public int Port; //这个服务器需要开启的场景列表(这个服务器为特定的一些场景提供服务,跳转场景则切另一个服务器为玩家服务) public List<SceneConfig> SceneConfigs { get; } public Server() { SceneConfigs = new List<SceneConfig>(100); } } public class ServerConfig { #region 静态成员 //区服编号 public static int AreaServerId; //当前服务器类型 public static ConstDefine.ServerType CurrServerType; //当前服务器编号 public static int CurrServerId = 0; //Mongo连接字符串 public static string MongoConnectionString; //Redis连接字符串 public static string RedisConnectionString; //数据表路径 public static string DataTablePath; //区服内服务器列表 private static List<Server> ServerList; //场景和游戏服务器的对应字典(哪个场景在哪个服务器上运算 SceneId:SceneConfig) public static Dictionary<int,SceneConfig> DicSceneInServer; //游戏服务DB名(一个区服务,一个DB??一个区服如果只使用一个DB,很多个服务同时像这一个DB写数据的话不会造成拥堵吗??) private static string m_GameServerDBName = null; public static string GameServerDBName { get { if (string.IsNullOrEmpty(m_GameServerDBName)) m_GameServerDBName = string.Format("GameServer_{0}", AreaServerId); return m_GameServerDBName; } } //角色HashKey(就是个Key,看代码好像是一个区服只能有一个Role啊,目前没看到哪里用) private static string m_RoleHashKey = null; private static string RoleHashKey { get { if (string.IsNullOrEmpty(m_RoleHashKey)) m_RoleHashKey = string.Format("{0}_RoleHash", AreaServerId); return m_RoleHashKey; } } //角色昵称Key(玩家名称) private static string m_RoleNickNameKey = null; public static string RoleNickNameKey { get { if (string.IsNullOrEmpty(m_RoleNickNameKey)) m_RoleNickNameKey = string.Format("{0}_NickName", AreaServerId); return m_RoleNickNameKey; } } public static void Init() { string path = AppDomain.CurrentDomain.BaseDirectory + "Configs/ServerConfig.xml"; XDocument doc = XDocument.Load(path); XElement itemRoot = doc.Root; AreaServerId = itemRoot.Element("AreaServerId").Value.ToInt(); CurrServerType = (ConstDefine.ServerType)itemRoot.Element("CurrServerType").Value.ToInt(); CurrServerId = itemRoot.Element("CurrServerId").Value.ToInt(); MongoConnectionString = itemRoot.Element("MongoConnectString").Value; RedisConnectionString = itemRoot.Element("RedisConnectString").Value; DataTablePath = itemRoot.Element("DataTablePath").Value; ServerList = new List<Server>(); DicSceneInServer = new Dictionary<int, SceneConfig>(); //初始化服务器节点 XElement itemServer; IEnumerator<XElement> iterServer = itemRoot.Element("Servers").Elements("Item").GetEnumerator(); for (; iterServer.MoveNext();) { itemServer = iterServer.Current; ServerList.Add(new Server() { CurrServerType = (ConstDefine.ServerType)itemServer.Attribute("ServerType").Value.ToInt(), ServerId = itemServer.Attribute("ServerId").Value.ToInt(), Ip = itemServer.Attribute("Ip").Value, Port = itemServer.Attribute("Port").Value.ToInt() }) ; } //初始化场景对应的服务器 XElement itemScene; SceneConfig sceneCfg; Server server; int sceneId; int serverId; string aoiJsonDataPath; IEnumerator<XElement> iterScene = itemRoot.Element("Scenes").Elements("Item").GetEnumerator(); for (; iterScene.MoveNext();) { itemScene = iterScene.Current; sceneId = itemScene.Attribute("SceneId").Value.ToInt(); serverId = itemScene.Attribute("ServerId").Value.ToInt(); aoiJsonDataPath = itemScene.Attribute("AOIJsonDataPath").Value; sceneCfg = new SceneConfig() { SceneId = sceneId, ServerId = serverId, AOIJsonDataPath = aoiJsonDataPath }; //保存场景对应的服务器 DicSceneInServer[sceneId] = sceneCfg; //获取对应的服务器,正向写入该服务器会服务哪些场景 server = GetServer(ConstDefine.ServerType.GameServer, serverId); if (null != server) { server.SceneConfigs.Add(sceneCfg); } } Console.WriteLine("ServerConfig Init Complete"); } public static Server GetServer(ConstDefine.ServerType type,int serverId) { int iLen = ServerList.Count; Server server = null; for (int i = 0; i < iLen; ++i) { server = ServerList[i]; if (server.CurrServerType == type && server.ServerId == serverId) return server; } return null; } #endregion } }
这个笔记写完啦!