지난 시간에 Action과, 람다를 이용해 함수를 담고 실행시켜주었다. 이와 다른 방법도 가능해서 테스트를 해보고자 한다.
TaskQueue라는 새항목을 생성하고, interface ITask를 생성 하고 Excute()
라는 함수 틀 하나를 만들어 준다.
일 처리에 필요한 함수에 맞도록 Class 생성해준다. 여기서는 예시로 BroadCast를 사용한다. 필요한 변수와 값들을 담아주었다.
BroadCast()
시에 필요한 변수들을 선언하고, 생성자를 통해 처음 생성 될때 값이 들어가게 해주고, 해당 함수를 실행시키면 내부에 Excute 함수를 통해 호출 해주는 방식으로 구현을 할 수 있다.
아래는 기존 BroadCast 함수이다.
동작 시키는 방법은 지난 시간에 했던 Flush() 같은 곳에서 처리를 해주는 건 유사하다.
하나의 쓰레드가 맡아서, Queue에 담긴 걸 Pop()하여 처리 하던 Flush()
실무에서 이러한 구조로 자주 사용이 되고 있기에 알아둘 필요가 있지만 강사님은 지난 시간의 JobQueue 방식을 선호한다고 한다.
나도 코드를 봤을 때 더 깔끔하게 작성 가능한 지난 시간이 나아 보인다.
선택은 자유롭게 하면되고, JobQueue의 핵심 내용은 처음에 lock을 이용해 구현했을 때는 대기하는 쓰레드가 생기고, 쓰데르 풀에서 추가 쓰레드를 만들며 악순환이 발생했었는데
그것을 하나의 쓰레드가 맡아 Queue에 하나씩 담겨진 일감을 순차적으로 처리하도록 진행시켰다는 점이다.
존 형식의 게임의 경우 (바람의나라) 맵을 넘어 갈 때와 같은 상황에서 이동 시에 로딩을 하는 기간이 있기에, zone 하나의 단위에 JobQueue를 넣어 처리하도록 만들면 되기에 비교적 간단하다.
하지만 와우, 리니지와 같은 심리스 게임은 어떻게 할지 고민을 해야한다. GameRoom이 아닌 넓은 맵에서 임의로 영역을 구분하여 JobQueue를 두고 처리를 할 수도 있지만, 그렇게 구분된 영역 사이에서 어떻게 처리 할지 애매한 상황이 생길 수 있다.
이때 실무에서는 모든 객체(몬스터, 스킬, 유저 등) 에서 일감을 순차로 처리할 수 있게 모든 곳에 JobQueue를 배치하여 사용하기도 한다. 어떠한 방식인지 완벽하게는 아니어도 차이점이 있다는 부분은 이해가 된다.
더 많은 유저들이 접속했을 때의 부하 테스트를 해보기 위해서는 기존의 구조 변경이 필요하다.
기존에는 최대 대기 수를 10명으로 제한을 해두어서, 동시에 여러명이 접속할 경우 연결 조차 잘 안될 수도 있는 구조다.
이 부분에서 대기 수를 최대 100명으로 까지 늘리고, register 만큼 for문을 돌려 문지기를 10번 더 생성 하여 더 많은 클라이언트를를 받을 수 있게 수정해준다.
이제 클라이언트 접속 인원을 500명으로 늘려보자. 실제로 마을 같은 곳이 아니고 동시에 이정도로 많이 접속하는 경우는 많지 않지만 부하 테스트를 해보는 것이기 때매 진행한다.
메모리가 유지 되지 않고, 지속 상승하는 구조라면 좋은 신호가 아니다고 볼 수 있다. (계속 일감이 밀리고 있다고 볼 수 있는 상황)
실제 문제가 발생하고 있는 부분은 BroadCast에서 foreach를 돌며 계속 Send 날리는게 어마어마하게 부담이 되고있다.
500명에서 0.25초 마다 패킷을 날리고 서로에게 뿌려주고 있는 상황이다.(초당 약 1만 번의 패킷 전송 발생)
N^2의 점점 느려지는 나쁜구조인데, 이걸 개선하기 위해서 패킷을 모아 보내는 방식을 사용할 수 있다.
Queue에 계속 쌓아 두었다가, 일정 시간이 지날 때 마다 Send를 한 번씩만 해주는 구조로 바꾸면 더 개선을 할 수도 있다.
BroadCast 방식이라면 모두 패킷 모아 보내기 처리를 함. 다만 어디서 할지는 고민을 더 해보아야한다.
다음 시간에 이 부분을 처리할 것이고 오늘은 선행 지식 공부가 진행되었다.