초기커밋
This commit is contained in:
234
ServerCommon/Helper/LoadBalanceServerHelper.cs
Normal file
234
ServerCommon/Helper/LoadBalanceServerHelper.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
|
||||
|
||||
using WORLD_META_ID = System.UInt32;
|
||||
|
||||
|
||||
namespace ServerCommon;
|
||||
|
||||
public static class LoadBalanceServerHelper
|
||||
{
|
||||
private const int READ_SERVER_DATA_LIMIT_COUNT = 5;
|
||||
private const int FULL_LIMIT_RATE = 100;
|
||||
|
||||
public static async Task<ServerInfo?> getAuthLoginToChannelServerInfo( this IWithServerMetrics serverMetrics
|
||||
, EntityBase entityUser
|
||||
, UInt16 worldId = 0 )
|
||||
{
|
||||
if (0 >= worldId)
|
||||
{
|
||||
worldId = getWorldIdWenServerChange(entityUser);
|
||||
}
|
||||
|
||||
return await getBalancedServerInfo(serverMetrics, entityUser, ServerType.Channel, ServerMoveType.Auto, worldId);
|
||||
}
|
||||
|
||||
public static async Task<ServerInfo?> getReturnToServerInfo( this IWithServerMetrics serverMetrics
|
||||
, string toReturnServerName, ServerType toReturnServerType
|
||||
, EntityBase entityUser, ushort worldId = 0 )
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
|
||||
(var result, ServerInfo ? found_server_info) = await serverMetrics.getServerInfoByServerName(toReturnServerName);
|
||||
if (result.isSuccess() && null != found_server_info)
|
||||
{
|
||||
return found_server_info;
|
||||
}
|
||||
|
||||
found_server_info = await getBalancedServerInfo(serverMetrics, entityUser, toReturnServerType, ServerMoveType.Auto, worldId);
|
||||
if(null != found_server_info)
|
||||
{
|
||||
return found_server_info;
|
||||
}
|
||||
|
||||
err_msg = $"Not found ServerInfo !!!, in getReturnToServerInfo() : {result.toBasicString()} - {entityUser.toBasicString()}, {serverMetrics.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<ServerInfo?> getBalancedServerInfo( this IWithServerMetrics IWithServerMetrics
|
||||
, EntityBase entityUser
|
||||
, ServerType toServerType, ServerMoveType serverMoveType
|
||||
, UInt16 worldId = 0 )
|
||||
{
|
||||
string err_msg;
|
||||
|
||||
// 1. 모든 서버 리스트 가져오기
|
||||
var loaded_servers = await getAllServersPassableEntered(IWithServerMetrics, toServerType, worldId);
|
||||
if (!loaded_servers.Any())
|
||||
{
|
||||
err_msg = $"ServerMetrics count zero !!! toServerType:{toServerType}, worldId:{worldId} - {entityUser.toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 이동 타입에 따른 체크
|
||||
switch (serverMoveType)
|
||||
{
|
||||
case ServerMoveType.Auto:
|
||||
return await selectServerInfoFromList(loaded_servers.ToList(), entityUser, MetaHelper.GameConfigMeta.AutoMoveRate);
|
||||
case ServerMoveType.Force:
|
||||
return await selectServerInfoFromList(loaded_servers.ToList(), entityUser, FULL_LIMIT_RATE);
|
||||
case ServerMoveType.Return:
|
||||
case ServerMoveType.None:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<ServerInfo?> selectServerInfoFromList(IReadOnlyList<ServerInfo> servers, EntityBase entityUser, int limitRate)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
ServerInfo? select_server = null;
|
||||
ServerInfo? language_server = null;
|
||||
var check_user_count = -1;
|
||||
|
||||
var account_attribute = entityUser.getOriginEntityAttribute<AccountAttribute>();
|
||||
if (null == account_attribute) return null;
|
||||
|
||||
foreach (var server in servers)
|
||||
{
|
||||
var current_user_count = checkCurrentUserCount(server);
|
||||
|
||||
// 1. max count 체크
|
||||
var max_user_count = server.Capacity * limitRate / 100;
|
||||
if (max_user_count <= current_user_count) continue;
|
||||
|
||||
// 2. current session count 체크
|
||||
if (check_user_count >= current_user_count) continue;
|
||||
|
||||
select_server = server;
|
||||
check_user_count = current_user_count;
|
||||
}
|
||||
|
||||
return select_server ?? language_server;
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<ServerInfo>> getAllServersPassableEntered( this IWithServerMetrics serverMetrics
|
||||
, ServerType toServerType, WORLD_META_ID worldMetaId )
|
||||
{
|
||||
for (var i = 0; i < READ_SERVER_DATA_LIMIT_COUNT; i++)
|
||||
{
|
||||
// 1. 서버 정보 가져오기
|
||||
(var result, var found_server_infos) = await serverMetrics.getServerInfosByServerType(toServerType, worldMetaId);
|
||||
if (result.isFail())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. 서버 최대 세션수 체크
|
||||
// 서버의 최대 세션수보다 (현재 세션수 + 예약자 수 + 복귀자 수 + Beacon 수)가 크거나 같을때 목록에서 제외시킨다.
|
||||
found_server_infos.RemoveAll(x => checkCurrentUserCount(x) >= x.Capacity);
|
||||
|
||||
return found_server_infos;
|
||||
}
|
||||
|
||||
return new List<ServerInfo>();
|
||||
}
|
||||
|
||||
private static UInt16 getWorldIdWenServerChange(EntityBase entityUser)
|
||||
{
|
||||
UInt16 target_world_id = 0;
|
||||
|
||||
// 1. 기본 Default 정보 확인
|
||||
if (!MetaData.Instance._GameConfigMetaTable.TryGetValue(ConstantKeyType.DefaultEntryWorldIdWhenLoginToAuth.ToString(), out var found_value))
|
||||
{
|
||||
var err_msg = $"ConstantKeyType.DefaultEntryWorldIdWhenLoginToAuth not found !!! : worldId:{found_value} - {entityUser.toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. LastConnectionChannel 정보 확인
|
||||
var location_attribute = entityUser.getOriginEntityAttribute<LocationAttribute>();
|
||||
if (null == location_attribute) return target_world_id;
|
||||
|
||||
target_world_id = (location_attribute.LastestChannelServerLocation.WorldMetaId == 0)
|
||||
? Convert.ToUInt16(found_value)
|
||||
: (UInt16)location_attribute.LastestChannelServerLocation.WorldMetaId;
|
||||
|
||||
return target_world_id;
|
||||
}
|
||||
|
||||
private static int checkCurrentUserCount(ServerInfo server) => server.Sessions + server.Reservation + server.ReturnCount + server.UgcNpcCount;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// *인스턴스 룸을 생성할 인스턴스 서버 고르기*<br/>
|
||||
/// 인스턴스 룸 최대 인원이 들어갈 수 있는 서버 중 수용인원이 가장 많은 서버 선택
|
||||
/// </summary>
|
||||
/// <param name="serverList">인스턴스 서버 목록</param>
|
||||
/// <param name="roomCapacity">생성할 인스턴스 룸 최대 인원</param>
|
||||
/// <returns>입력값 List<ServerInfo> serverList 의 인덱스, 선택된 서버가 없는 경우 -1</returns>
|
||||
public static int getBestInstanceServerIndexForCreate(in List<ServerInfo> serverList, int roomCapacity)
|
||||
{
|
||||
int retIndex = -1;
|
||||
int maxCount = 0;
|
||||
|
||||
foreach (var (server_info, index) in serverList.Select((value, index) => (value, index)))
|
||||
{
|
||||
if (maxCount < server_info.RoomCapacity + roomCapacity && server_info.RoomCapacity + roomCapacity <= server_info.Capacity)
|
||||
{
|
||||
retIndex = index;
|
||||
maxCount = server_info.RoomCapacity + roomCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
return retIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// *게임 서버 고르기*<br/>
|
||||
/// 서버 수용인원의 80% 되지 않은 서버에서 선택<br/>
|
||||
/// 모든 서버가 80% 이상인 경우 서버 수용인원을 넘지 않은 서버에서 선택
|
||||
/// </summary>
|
||||
/// <param name="serverList">게임 서버 목록</param>
|
||||
/// <returns>입력값 List<ServerInfo> serverList 의 인덱스, 선택된 서버가 없는 경우 -1</returns>
|
||||
public static int getBestGameServerIndex(List<ServerInfo> serverList, LanguageType languageType
|
||||
, ref int currentServerIndex)
|
||||
{
|
||||
int server_index = -1;
|
||||
int limit_first = Constant.g_MaxUser * 5 / 10;
|
||||
|
||||
/*
|
||||
foreach (var serverInfo in serverList.Select((value, index) => new { value, index }))
|
||||
{
|
||||
if (serverInfo.value.Language == languageType &&
|
||||
limit_first > serverInfo.value.Sessions)
|
||||
{
|
||||
serverIndex = serverInfo.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (serverIndex == -1)
|
||||
{
|
||||
foreach (var serverInfo in serverList.Select((value, index) => new { value, index }))
|
||||
{
|
||||
if (limit_first > serverInfo.value.Sessions)
|
||||
{
|
||||
serverIndex = serverInfo.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (server_index == -1)
|
||||
{
|
||||
if (currentServerIndex >= serverList.Count)
|
||||
{
|
||||
currentServerIndex = 0;
|
||||
}
|
||||
|
||||
server_index = currentServerIndex;
|
||||
|
||||
++currentServerIndex;
|
||||
}
|
||||
|
||||
return server_index;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user