공부/인프런 - Rookiss

Part 4-5-5. Job Queue : Job Queue #2

셩잇님 2023. 12. 28. 11:53
반응형

 

 

Job Queue

 

 지난 시간에는 Action과 람다식을 이용해 함수를 직접적으로 실행하는 것이 아닌, 스레드에게 일감을 주는 형태로 변경하는 시간을 가졌다. 오늘은 똑같이 동작하지만 수동적으로 Task를 만들어주는 수동적인 방법에 대해서 알아보도록 한다.

 


 

📧 Task Queue

 

 Task Queue라는 새로운 클래스를 서버 프로젝트 밑에 새롭게 생성하고 interface ITask를 새롭게 생성해준다. 이 후 Excute()라는 메소드를 생성해준다.

 

 

 일 처리가 필요한 함수(Enter, Leave, BroadCast 등)에 맞도록 클래스를 새롭게 만들어준다. 예시로는 BroadCast를 만들어 볼것이다. 아래와 같이 작성하여 필요한 변수와 값들을 담아주도록 하자.

 

 

 이전 시간처럼 실행시켰던 BroadCast 메서드와 같이 필요한 변수들을 선언하고, 생성자를 통해 처음 생성될 때에 값이 들어가게 해도록 한다. 이 후 해당 함수를 실행시키면 내부에 Excute 메서드를 통해 함수가 호출되는 방식으로 구현하는 것이다.

 

기존에 사용했던 GameRoom 내 BroadCast 메서드

 

 이를 동작시키는 방법은 지난 시간에 했던 Flush()와 같은 메서드에서 처리하도록 한다. 이 부분은 유사하다. 

 

 

현업과 같은 실무에서는 람다식이라는 개념이 형성된지 얼마 되지 않아 수동적으로 일 처리가 필요한 함수들을 구현해서 처리하는 형식으로 자주 사용되기 때문에 알아둘 필요가 있다. 하지만 이런식으로 처리한다면 일 처리가 필요한 함수를 모두 구현해야 하기 때문에.. 람다식을 이용해서 사용하는 방법이 보다 편리해보인다.

 

결론 😎

 수동적으로 생성하는 방식, 람다식을 이용해서 사용하는 방식 중 선택은 본인에게 편한 방법을 사용하면 되는 것이다. 즉. 핵심은 처음에 lock을 이용해 구현했을 때에는 대기하는 쓰레드가 생기고, 생성되었던 쓰레드가 돌아오지 않아 쓰레드 풀에서 추가 쓰레드를 만들며 악순환이 발생했었던 것을 하나의 쓰레드가 일 처리 담당 쓰레드가 되어 다른 쓰레드들은 Queue에 자신의 일감을 넘겨주어 순차적으로 일감을 처리하도록 진행시켜주도록 한 것이다.

 


 

🌏 존(Zone) 형식과 게임과 심리스(Seamless) 형식의 게임

 

 바람의 나라와 같은 존 형식의 게임의 경우 맵을 넘어갈 때 로딩을 하는 시간이 있기에, 부여성과 같은 하나의 존 단위에 JobQueue를 넣어 처리하도록 만들면 되기 때문에 비교적 JobQueue 활용 처리가 용이하다.

 

존 게임의 대표적인 형태인 바람의나라

 

 그러나 리니지, 와우와 같은 심리스 게임은 JobQueue의 활용 처리를 어떻게 해야할지 고민이다. GameRoom이 아닌 넓은 맵에서 임의로 영역을 구분하여 JobQueue를 두고 처리할 수는 있겠지만, 이렇게 된다면 구분된 영역 사이에서 어떻게 처리할 지에 대한 의문점이 생길 수 밖에 없다.

 

심리스 게임의 대표적인 형태인 와우

 


 

🧟 테스트 환경 개선

 

 더 많은 유저들이 접속했을 떄의 부하 테스트를 하기 위해서는 기존 로직의 변경이 필요하다.

 

🧗‍♂️ Listener

 

 기존 코드에서는 문지기 즉 Listner를 10명으로 제한해두었기 때문에, 동시에 여러명이 접속할 경우 연결이 정상적으로 되지 않는 구조이다. 따라서 아래와 같이 수정하여 최대 100명으로 늘려서 더 많은 클라이언트들이 접속할 수 있도록 수정해준다. 

 

변경 전

 

변경

 

🧗‍♂️ 부하 테스트

 

 이제 클라이언트 접속 인원을 100명보다 더 큰 500명으로 늘려보도록 하자. 실제로 마을 같은 곳이 아니고 동시에 이 정도로 많은 사람들이 접속하는 경우는 많지 않지만 테스트를 위해 이를 진행한다. 실행한다면 메모리가 일정 수준으로 유지되지 않고, 지속 상승하는 것을 볼 수 있다. 이는 곧 좋은 징조는 아니다. 왜냐하면 일감이 계속 밀리기 때문에 메모리가 생성되기 때문이다.

 

 

 확인해보면 실제로 문제가 발생하고 있는 부분은 BroadCast에서 foreach 문을 순회하며 계속해서 Send를 하고 있는 것이 큰 부담으로 나타나는 것을 볼 수 있다. 왜냐하면 500명에서 0.25초마다 패킷을 계속해서 날리고, 이를 뿌려주고 있기 때문이다. 이는 곧 초당 1만번의 패킷 전송이 발생한다고 볼 수 있다.

 

 

 따라서 이는 N^2의 시간복잡도를 가지는데, 이를 개선하기 위해서는 패킷을 매 틱마다 보내는 것이 아닌 한번에 모아 보내는 방식을 사용할 수 있다. 즉 Queue에 Send할 내용을 모아서 쌓아두었다가 일정 시간, 혹은 조건에 따라 Send를 한 번씩 해주는 구조로 변경하는 것이다. 이 부분은 다음 시간에 학습해보도록 하자.

 

 

반응형