GithubHelp home page GithubHelp logo

k2proto's People

Contributors

alkee avatar alkee-allm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

k2proto's Issues

Unreal project(dedicated server)에 gRPC server 적용

game server(UE4 dedicated server)에서도 gRPC backend 가 필요(#25 및 client 로 event 전달에 사용)하기 때문에, 이를 위한 서비스가 추가되어야 할 것.

  • Unreal 의 servier side(dedicated server) 코드에만 포함되도록.
  • 서버가 실행되는 경우 backend service로 register 동작(#26, #15 참고) ; k2svc 의 servermanager 로 연결(별도의 설정파일 사용할 것 - 테스트 환경에 따라 별도 빌드 없이 서버주소 바꿔 실행할 수 있도록)
  • register 이후에 일정시간 간격으로 ping 동작
  • grpc server 기능(BackendHost)을 포함하고 k2svc sample 의 session server 가 재연결 될 때 발생하는 updatebackend를 받아 SessionManager 의 정보 업데이트

ServiceConfiguration 의 listening url 정보를 override 할 수 없는 문제

ServiceConfiguration(#3)이 구성되었지만, 이는 StartUp.Configure 함수실행 이후에만 사용 가능하다.

따라서, 이전에 설정되어야 하는 listeningUrl 정보는 사용할 수 없다. 예)

.ConfigureWebHostDefaults(webBuilder =>
{
	var urls = new List<string>();
	urls.Add(config.BackendListeningAddress);
	urls.Add(config.FrontendListeningAddress);
	// config 의 값은 기본생성자 값이다. appsettings 에서 설정되기 전 상태.

	webBuilder
	.UseKestrel()
	.UseUrls(urls.ToArray()) // 따라서 appsetting 에 따라 이 값이 설정되지 않는다.
	.UseStartup<Startup>();
});

server configuration 정책 변경

현재는 commandline argument 로 server management service 에 연결될 주소(serverManagementBackendAddress)를 입력받아 사용중.

k2proto/K2svc/Program.cs

Lines 26 to 30 in b35b11d

if (Uri.TryCreate(args[0], UriKind.Absolute, out Uri uri)
&& (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
{
serverManagementBackendAddress = args[0];
}

실제 서비스 상태에서는 이 값이 거의 고정되어 사용될 예정이고, container 추가에 따른 설정(ip, port, server id)들이 가장 빈번하게 바뀔 것. network 내에서 유일한 서비스들(unique backend service)의 경우 거의 고정된 설정을 유지할 것으로 보이며, game server 등의 frontend service 의 scale out 시에 변경될 설정들을 가장 간편하게 설정할 수 있어야 할 것.

text 파일 encoding 문제

많은 파일들이 cp494 encoding으로 저장되어있어 utf-8 로의 변환이 필요하다.

c++ 의 경우 compiler 옵션까지 바꿔줘야하고 windows visual studio 가 c++ project 의 경우 새 파일 template 들이 ANSI 로 되어있으므로 번거로울 수 있겠지만,

적어도 c# project(K2svc)내 파일들은 모두 UTF-8 로 바꿔야 할 것.

appsettings.json 파일을 찾지 못하는 문제

단일 파일 배포를 사용해 k2svc.exe 를 실행(publish directory)했을 때,

 ./K2svc.exe
Unhandled exception. System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\Users\non-setting\AppData\Local\Temp\.net\K2svc\we50w3bn.4hb\appsettings.json'.
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.HandleException(ExceptionDispatchInfo info)
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
   at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
   at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
   at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
   at K2svc.Program.LoadConfig(String[] args)
   at K2svc.Program.Main(String[] args)

와 같은 exception(crash) 발생

참고

SecurityKey 적용후 서버 크래시

issue #2 완료후 테스트가 미진하여 아래와 같은 크래시(exception) 발생

예외 발생: 'System.ArgumentOutOfRangeException'(Microsoft.IdentityModel.Tokens.dll)
'System.ArgumentOutOfRangeException' 형식의 예외가 Microsoft.IdentityModel.Tokens.dll에서 발생했지만 사용자 코드에서 처리되지 않았습니다.
IDX10603: Decryption failed. Keys tried: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
Exceptions caught:
 '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
token: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'
>	K2svc.dll!K2svc.Frontend.InitService.GenerateJwtToken(string id) 줄 69	C#
 	K2svc.dll!K2svc.Frontend.InitService.Login(K2.LoginRequest request, 
        Grpc.Core.ServerCallContext context) 줄 39	C#

parameter 에 appsettings 경로를 받을 수 있도록

분리된 server instance test(#53) 진행하는 중, directoryy 별로 구성(appsettings)을 다르게 구성했는데, settings 을 변경해야할때마다 directory 를 바꿔가며 작업하는것이 불편. 이를 개선하기 위해 parameter 로 appsettings 파일(#57)을 입력받을 수 있다면 어떨까?

Unreal lobby client 가능성 검토

현재까지는 google 문서에서 정리하고 별도의 processor 로 진행하게 될 확률이 높지만, 프로젝트 완성도 면에서는 uniprocessor(unreal client)로 진행하는 것이 좋기 때문에, 교려사항들을 최대한 확인하고 빠른 최종 결정이 필요.

고려사항

  • 병렬 작업 환경
  • 문제 해결 환경(디버깅 등)
  • 개발 환경
  • 유지보수 환경(인력 충원, 교육 난이도 등)

PR label 추가

github action을 이용해, 해당 issue 에 대한 pull request 가 만들어지면 자동으로 PR or Pull requested label 이 해당 issue 에 붙고, pull request 가 종료(merged or declined)되면 자동으로 이 label 이 제거되도록 구성.

참고

GameServer 관리 기능 추가

k2 의 game session 이 unreal dedicated server(이하 game server) 로 실행되는 환경임을 감안할 때,

lobby 에서 party/team 이 결정되고 in-game 에 진입할때 process 를 실행하거나, 이미 실행되고 비어있는 game server 를 찾아 접속정보를 알려 주어야 한다. 또한, 필요한 경우 사용되지 않는 game server 를 shutdown 할 수 있어야 한다.

ping timeout 처리

일정시간동안 ping 이 없는 서버들의 경우 장애처리.

상황에 대한 함수를 별도로 만들어 추후에 정책적인 부분이 변경되더라도 해당 함수를 수정하는 것으로 반영되도록.

unique backend service 의 경우 별도 issue(#38) 에서 진행.

GRPC client 적용 Unreal project 추가

C++ K2Client sample 참고해, unreal project(UE4)에서 gRPC client 적용이 필요.

  • UE4 project 의 크기(용량) 최소화 유지 - 버전관리
  • .gitignore 알맞게 추가 또는 수정
  • 비동기 방식(#1) 또는 별도 threading 을 이용해, rendering 을 멈추지 않고 RPC 를 사용할 수 있도록 ; 요청(request)시 loading 표시 및 응답(response)시 loading 해제.
  • server(dedicated server) 및 client code 코드 양쪽에서 사용 가능하도록 구성되어야 할 것.

GRPC 적용 unity client 추가

client sample 이 c++ 코드로 되어있으나, K2 lobby 가 분리되어 C#(unity?)으로 개발될 수 있기 때문에, 이를 위한 sample 작업이 필요.

backend(unique) service장애시 처리

backend(서버들의 서버) server 가 장애가 발생한 경우, 그리고 다시 재 연결이 된 경우에 알맞은 동작(서비스 계속 진행)을 수행해야한다.

#37 작업진행이 선행 되어야 할 것.

k2svc 의 README.md 작성

프로젝트 교육 목적의 메뉴얼 작성.

구조적인 설명, 실행 순서 설명 및 각 이벤트 발생상황에 대한 설명이 필요할 것.

또한, 가상 작업 시나리오(study-case)를 정해 작업하는 방식을 기술해 보는 것도 좋을 듯.

push broadcast 는 push service 로만 전달

public override async Task<Null> Broadcast(PushRequest request, ServerCallContext context)
{
List<Server> all;
lock (servers) all = new List<Server>(servers);
foreach (var s in all)
{
if (s.HasPush == false) continue;
var client = clients.GetClient<ServerHost.ServerHostClient>(s.BackendListeningAddress);
await client.BroadcastAsync(request, header);
}
return new Null();
}

현재 broadcast 시에, 연결된 모든 server 에 PushRequest 를 전달하고있는데, 대상은 PushService frontend 를 제공하고 있는 서버들에 한정되어야 한다. 다만, PushService 와 관련없는 서버 관리 목적의 경우 전체 서버에 메시지를 전달하는 방식은 유지 필요.

jwt timeout 및 재인증 절차 추가

jwt 의 validation lifetime 기능을 활성화하고 이 시점이 되기 전에 재인증(jwt 갱신)받을 수 있는 기능을 추가

k2proto/K2svc/Startup.cs

Lines 41 to 53 in 0aeb1da

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateActor = false,
ValidateLifetime = false,
IssuerSigningKey = Security.SecurityKey
};
});

ping response 받은 frontend 의 crash

Frontend server를 먼저 띄우고 ServerManager 를 띄우는 상황에 가끔씩 발생.

Console log:

warn: K2svc.Background.ServerManagementBackground[0]
      ERROR on ping : Service is unimplemented.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 POST http://[::1]:9060/K2B.ServerHost/Stop application/grpc
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /K2B.ServerHost/Stop'

Debug output:

예외 발생: 'System.ApplicationException'(K2svc.dll)
'System.ApplicationException' 형식의 예외가 K2svc.dll에서 발생했지만 사용자 코드에서 처리되지 않았습니다.
invalid backend request of /K2B.ServerHost/Stop from ipv6:[::1]:65282

Call stack:

>	K2svc.dll!K2svc.Filter.BackendValidator.UnaryServerHandler<K2B.StopRequest, K2B.Null>(K2B.StopRequest request, Grpc.Core.ServerCallContext context, Grpc.Core.UnaryServerMethod<K2B.StopRequest, K2B.Null> continuation) 줄 31	C#
 	[외부 코드]	
 	K2svc.dll!K2svc.Startup.Configure.AnonymousMethod__0(Microsoft.AspNetCore.Http.HttpContext context, System.Func<System.Threading.Tasks.Task> next) 줄 79	C#
 	[외부 코드]	

Screenshot:
image

Detail:

$exception


  | 이름 | 값 | 형식
-- | -- | -- | --
◢ | $exception | {"invalid backend request of /K2B.ServerHost/Stop from ipv6:[::1]:65282"} | System.ApplicationException
  | ▶ Data | {System.Collections.ListDictionaryInternal} | System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
  | HResult | -2146232832 | int
  | HelpLink | null | string
  | ▶ InnerException | null | System.Exception
  | Message | "invalid backend request of /K2B.ServerHost/Stop from ipv6:[::1]:65282" | string
  | Source | "K2svc" | string
  | StackTrace | "   at K2svc.Filter.BackendValidator.UnaryServerHandler[TRequest,TResponse](TRequest request, ServerCallContext context, UnaryServerMethod`2 continuation) in C:\\work\\local\\K2\\K2svc\\Filter\\BackendValidator.cs:line 32\r\n   at Grpc.Shared.Server.InterceptorPipelineBuilder`2.<>c__DisplayClass5_0.<<UnaryPipeline>b__1>d.MoveNext()" | string
  | ▶ TargetSite | {System.Threading.Tasks.Task`1[TResponse] UnaryServerHandler[TRequest,TResponse](TRequest, Grpc.Core.ServerCallContext, Grpc.Core.UnaryServerMethod`2[TRequest,TResponse])} | System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
  | ▶ Static members |   |  
  | ▶ Non-Public members |   |  


Backgroundservice timer blocking 문제

ServerManagementBackground에서 Ping 이나 Register 할 때, timer 가 block 되는 방식으로 구현이되어있다보니, 이 timer 에서 await 응답을 늦게 받거나 멈추어버리면(debugging break point 등) 이 timer 가 멈추어 다른 연결된 요청도 함께 늦어지게되는 문제가 있다.

Server management backend 의 테스트 환경

현재 구조에서는 별도의 server management backend 를 통해 서버의 configuration 을 가져와서 시작하게 되어있음.

테스트를 위해 하나의 instance 로 서버를 실행할 때 구조적인 제약(server management backend 필요)으로 서비스를 시작할 수 없다.

현재 테스트를 위해

k2proto/K2svc/Program.cs

Lines 31 to 34 in 0aeb1da

// argument 가 없는 경우라면 개발(local) 버전이므로 ServerManagementService 가 떠있기 전 상태라 config 를 얻어올 수 없다
// 따라서 이 경우 기본값 사용
var config = args.Length == 0 ? new ServiceConfiguration() : await LoadConfig(rootAddress, args);

와 같이 처리하고는 있지만, Server management backend 의 Register 메시지를 디버깅할 수 없다.

또한, 이 서버가 server management backend 로 사용되는지에 대한 설정도 필요하다.

session 의 검증 문제

push service 에 연결이 끊어진 상태에서 grpc 호출(request) 했을 때, 이를 거부할 수 있어야 한다.(보안)

jwt 에 포함되어있는 pushserivce 로 해당 user 가 접속해 있는지를 확인하는 과정을 거쳐 request 가 실행되도록 하면, 매 요청마다 추가적인 request(backend)가 발생하겠지만, 중앙 집중적(UserSessionBackend)이 되지는 않을 것.

비동기 방식의 c++ client gRPC

현재 개발 편의를 위해 client 는 모두 동기 방식의 interface 만을 사용하고 있다.

이를 실제 사용을 위해 비동기 방식으로 전환해야할 것.

코드 내 TODO 를 issue 로 옮기기

protobuf 와 grpc 의 소스코드에 TODO 및 Hack comment 가 너무 많아 Visual stduio 작업목록을 이용해 관리하기가 어렵다. 코드 내 TODO 를 issue 로 옮겨 tracking 하는것이 나을 것 같다. (file 에 filter 를 적용하면 그나마 보기 쉬워지긴 한다.)

image

unreal dedicated server 최적화

현재 서버의 리소스 사용량이 너무 심각해 이를 상당히 줄여야 할 것.

2020-08-10 테스트 데이터

  • Disk read-write 는 매우 적음
  • 연결된 user 약 10명
  • 메모리 사용량 ; 500 MB
  • network(TCP) ; 88 KB / sec (received) + 1.4 MB / sec (sent) ; byte 단위이므로 네트워크에 주로 사용되는 bit 단위로 환산하려면 x8
  • CPU 사용량 ; 1개의 core 100%
Report Graph
perfmon2 prfmon1

자세한 데이터 확인 방법 : SamplePerfmon.zip 파일을 다운로드해 .blg파일을 열고 설정로드를 통해 sample.PerfmonCfg 파일을 로드.

참고 데이터(크리티카)

SSL 적용

현재 개발 편의를 위해 plain text http 를 이용하고 있으나, 보안 및 gRPC 의 원활한 사용(#15 Header 포함된 channel 사용 등)을 위해 https 로 프로토콜을 변경해야한다.

5b5b061 ssl 적용 sample 참고
Cannot Compose Insecure Credentials 참고

AWS ECS 서비스를 이용해 서버 확장이 용이하도록

현재, 간단한 구성(#15)을 위해 BackendListeningAddress(private IP + port) 와 FrontendListeningAddress(public IP + port)를 설정(환경변수 또는 appsettings.json)으로부터 입력받고 있음.

public string BackendListeningAddress { get; set; } = "http://localhost:5000"; // key 와 같이 사용됨. globally unique 해야할 것.
public string FrontendListeningAddress { get; set; } = "http://localhost:5000"; // NullOrEmpty 인 경우 frontend service disable

host 에서 docker run 실행 전 script 등을 통해 ip 및 port 정보를 얻어와 실행해줄 수 있을 것이라 생각했지만, AWS ECS를 사용하는 경우 이와같은 동작이 불가능(정적인 설정만 가능)하다는 @indralight 의견.

UE4 dedicated server 의 경우 1개의 dedicated server process 로는 1개의 game session(room) 만을 처리할 수 있는 듯 하기 때문에, 하나의 port 를 고정해서 사용하는 것(하나의 host 에 하나의 instance 만 사용 가능)은 상당히 비효율적일 수 있다.

참고

ECS 사용하는 경우 실행 전에 instance 의 ip 를 알아올 수 없기 때문에 환경변수로도 설정할 수 없고, 오직 port 지정만 가능. 따라서, container 내에서 동적으로 ip 를 얻어오는 장치는 필요하다.

분리된 server instance 테스트

backend 장애처리(#38)작업을 위해 일부 instance 를 분리해 실행(각 서비스별로 process 를 별도로 실행)해보았을 때 다양한 문제가 발생했음.

따라서, 분리된 instance 에서 테스트할 수 있는 환경을 구성하고, 발생하는 문제를 수정해야할 것.

Server management 기능 추가

public override Task<RegisterResponse> Register(RegisterRequest request, ServerCallContext context)
{
// TODO: server management here.
var server = new Server
{
Id = "dev",
FrontendListeningPort = 5001,
PushBackendAddress = "http://localhost:5000",
LastPingTime = DateTime.Now
};

현재 임시코드 부분을 실제 동작하도록 서버-관리 기능을 추가한다

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.