using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Net; using Sog.ClusterCfg; namespace Sog { public class ClusterApp { public string idc { get; private set; } public string BussinessName { get; private set; } public string Name { get; private set; } public uint ServerID { get; private set; } public string ServerIDStr { get; private set; } //外网 public IPEndPoint ExternalIPPort { get; private set; } //内网 public IPEndPoint InnerIPPort { get; private set; } public int listenAnyIP { get; private set; } //是否是主动连还是被动连 public bool IsClientCluster { get; private set; } public int BufferSize { get; private set; } public string Host { get; private set; } public string CfgPath { get; private set; } public string Cfgfile { get; private set; } //自定义参数key,value列表 public Dictionary ParamsMap { get; private set; } /// /// /// /// /// 多个inst的时候inst的偏移 public ClusterApp() { ParamsMap = new Dictionary(); } //根据配置文件解析我自己的配置和我相关有连接的app配置 public static void ParseWithMyAppId(ClusterConfig config, Dictionary appMap, uint serverId) { int worldid = (int)ServerIDUtils.GetWorldID(serverId); int apptype = (int)ServerIDUtils.GetServerType(serverId); int instid = (int)ServerIDUtils.GetInstanceID(serverId); string appname = GetAppNameByAppType(config, worldid, apptype); string groupname = null; BusinessConfig myBusiness = null; HostConfig myHost = null; GroupProcConfig myProc = null; GetMyHost(config, out myBusiness, out myHost); //添加自己 foreach (var group in myHost.groups) { GroupDeplayConfig groupconfig = GetGroupByName(config, group.groupname); foreach(var proc in groupconfig.procs) { if(proc.app == appname && proc.instid == instid) { myProc = proc; groupname = groupconfig.groupname; ClusterApp app = MakeClusterAppInfo(config, myBusiness, myHost, groupconfig, myProc, false); appMap.Add(app.ServerID, app); break; } } } //找到部署在当前host上的app group, 将group中与当前app有管道关系的加入appDict foreach (var host in myBusiness.hosts) { foreach (var group in host.groups) { GroupDeplayConfig groupconfig = GetGroupByName(config, group.groupname); foreach (var proc in groupconfig.procs) { if (proc.app == appname && proc.instid == instid) { } else { //有管道关系 int channelRelation = GetChannelRelation(config, appname, worldid, instid, host, proc); if (channelRelation != 0) { ClusterApp app = MakeClusterAppInfo(config, myBusiness, host, groupconfig, proc, channelRelation == 2); appMap.Add(app.ServerID, app); } } } } } } public static string GetAppNameByAppType(ClusterConfig config, int worldid, int apptype) { if(worldid == 0) { foreach(var app in config.cluster_layer_apps) { if(app.apptype == apptype) { return app.name; } } } else { foreach(var app in config.world_layer_apps) { if (app.apptype == apptype) { return app.name; } } } return null; } public static int GetAppTypeByName(ClusterConfig config, string appName, out bool isworldlayer) { isworldlayer = false; foreach (var app in config.cluster_layer_apps) { if (app.name == appName) { return app.apptype; } } foreach (var app in config.world_layer_apps) { if (app.name == appName) { isworldlayer = true; return app.apptype; } } return 0; } public static void GetMyHost(ClusterConfig config, out BusinessConfig business, out HostConfig host) { business = null; host = null; foreach (var tmpbusiness in config.bussiness) { foreach (var tmphost in tmpbusiness.hosts) { bool isMyHost = NetUtils.IsThisMachineAddress(tmphost.hostname); if (isMyHost) { business = tmpbusiness; host = tmphost; return; } isMyHost = NetUtils.IsThisMachineAddress(tmphost.innerip); if(isMyHost) { business = tmpbusiness; host = tmphost; return; } } } } public static GroupDeplayConfig GetGroupByName(ClusterConfig config, string groupname) { foreach(var group in config.groupdeploy) { if(group.groupname == groupname) { return group; } } return null; } public static int GetChannelRelation(ClusterConfig config, string myApp, int myWorldId, int myInstId, HostConfig otherHost,GroupProcConfig otherProc) { string otherApp = otherProc.app; int otherInstId = otherProc.instid; bool isworldlayer; int apptype = GetAppTypeByName(config, otherProc.app, out isworldlayer); int otherWorldId = isworldlayer ? otherHost.worldid : 0; //如果是world层的进程,缺省不支持跨world连接 if (myWorldId != 0 && otherWorldId != 0 && myWorldId != otherWorldId) { return 0; } foreach(var channel in config.channels) { //我连他 if(myApp == channel.app1 && otherApp == channel.app2) { // 同名服务, instId在前的主动连接所有后面的 if (myApp == otherApp) { return myInstId < otherInstId ? 1 : 2; } // 0 表示网状连接, 1 表示instId相同的app进行一对一连接 if (channel.type == 1) { return myInstId == otherInstId ? 1 : 0; } return 1; } //他连我 if (myApp == channel.app2 && otherApp == channel.app1) { // 同名服务, instId在前的主动连接所有后面的 if (myApp == otherApp) { return myInstId < otherInstId ? 1 : 2; } // 0 表示网状连接, 1 表示instId相同的app进行一对一连接 if (channel.type == 1) { return myInstId == otherInstId ? 2 : 0; } return 2; } } return 0; } public static ClusterApp MakeClusterAppInfo(ClusterConfig config, BusinessConfig business, HostConfig host, GroupDeplayConfig group, GroupProcConfig proc, bool isClientCluster) { ClusterApp app = new ClusterApp(); app.idc = host.idc; app.BussinessName = business.businessname; app.Host = host.hostname; app.CfgPath = host.cfgpath + "/" + proc.app; app.Cfgfile = host.cfgpath + "/" + proc.app + "/" + proc.cfg; //参数化的变量处理 ParseParams(business.param, app.ParamsMap); ParseParams(host.param, app.ParamsMap); ParseParams(proc.param, app.ParamsMap); if (string.IsNullOrEmpty(host.externalip) == false) { IPAddress addressExternal = IPAddress.Parse(host.externalip); app.ExternalIPPort = new IPEndPoint(addressExternal, proc.clusterport); } IPAddress address = IPAddress.Parse(host.innerip); app.InnerIPPort = new IPEndPoint(address, proc.clusterport); app.listenAnyIP = host.listenanyip; app.BufferSize = 1024000; app.IsClientCluster = isClientCluster; bool isworldlayer; int apptype = GetAppTypeByName(config, proc.app, out isworldlayer); app.ServerID = ServerIDUtils.MakeServerID(isworldlayer ? host.worldid : 0, apptype, proc.instid); app.ServerIDStr = ServerIDUtils.IDToString(app.ServerID); app.Name = proc.app + proc.instid; return app; } public static void ParseParams(string param, Dictionary ParamsMap) { if(string.IsNullOrEmpty(param)) { return; } if(param.Length == 0) { return; } string[] splits = param.Split(','); foreach(string split in splits) { if(string.IsNullOrEmpty(split)) { continue; } string[] keyvalue = split.Split('='); if(keyvalue.Length != 2) { continue; } string key = keyvalue[0]; string value = keyvalue[1]; if(string.IsNullOrEmpty(key)) { continue; } if(value == null) { value = ""; } key = key.Trim(); value = value.Trim(); if(key.Length == 0) { continue; } //添加 if(ParamsMap.ContainsKey(key) == false) { ParamsMap.Add(key, value); } else//更新 { ParamsMap[key] = value; } } } public static IPEndPoint GetRemoteIpEndPoint(ClusterApp thisApp, ClusterApp remoteApp) { IPEndPoint remoteIPEndPoint = remoteApp.InnerIPPort; //不是同一个idc并且远程机器可以接受外网连接 if (thisApp.idc != remoteApp.idc && remoteApp.listenAnyIP == 1) { remoteIPEndPoint = remoteApp.ExternalIPPort; } return remoteIPEndPoint; } } }