You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

377 lines
12 KiB

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<string,string> ParamsMap { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="config"></param>
/// <param name="instOff">多个inst的时候inst的偏移</param>
public ClusterApp()
{
ParamsMap = new Dictionary<string, string>();
}
//根据配置文件解析我自己的配置和我相关有连接的app配置
public static void ParseWithMyAppId(ClusterConfig config, Dictionary<uint, ClusterApp> 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<string, string> 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;
}
}
}