라이브 서비스를 위한 게임 서버 구성

3,140 views

Published on

2016년 3월 게임코디 게릴라 컨퍼런스(GCGC)에서 발표된 내용입니다.

Published in: Software
0 Comments
30 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,140
On SlideShare
0
From Embeds
0
Number of Embeds
79
Actions
Shares
0
Downloads
0
Comments
0
Likes
30
Embeds 0
No embeds

No notes for slide
  • 1회의 로그온 처리를 살펴보자
    로그온 담당 서버(인증 서버)에서 메시지 복호화
    DB에 쿼리 던지고 대기
    DB에서 쿼리 수행 후 응답
    클라에게 로그온 결과 보내주기

  • 게임 클라->인증 서버 접속
    인증 서버->DB 로그인 확인 query 실행
  • 동시접속자가 많으면 인증 서버 과부하
    로그온 메시지 복호화를 위한 연산 과정
    DB 서버에도 과부하
    쿼리 분석, 스토리지로부터 읽기 액세스
    데이터베이스의 양 자체는 과부하가 아님
    전세계 인구 60억명(6GB) * 1KB = 6TB  Scale-up으로도 충분히 해결
    그렇다면 인증 서버와 DB 서버를 scale-out할 수 있는 방법을 찾아야.

  • 데이터 분산을 할 수 있는가?  쉬움
    서로 다른 두 데이터간 상호작용할 일이 전혀 없음
    따라서 인증 서버를 그냥 나열해 버리자

    클라이언트는 인증 서버들 중 하나에 접속
    클라이언트는 서버 주소 목록을 갖고 있어서 랜덤으로 선택 후 접속
    (load balancer 혹은 L4 switch나 LB DNS를 적용하는 방법도 있으나 여기서는 논외)
    인증 서버는 플레이어 정보를 액세스하기 위해 데이터베이스에 쿼리 실행
  • 인증 서버는 부하가 분산되나, DB 서버가 여전히 과부하가 몰림
    DB 서버에 몰리는 쿼리 요청을 서로 다른 DB 서버로 분배하려면?

  • 데이터베이스를 데이터 분산 가능? 쉬움
    데이터베이스 내 플레이어 데이터들끼리 서로 상호작용하지 않으므로
    플레이어 정보들을 서로 다른 데이터베이스에 골고루 나눠 저장해 버리자
    클라는 인증 서버들 중 하나에 접속
    인증 서버는 유저ID 문자열에 대한 해시 함수를 실행하여, 대응하는 index의 DB에 query 실행
    DB 수를 M개에서 N개로 변경할 때, Hash(X,M)≠Hash(X,N)인 각 X 레코드를 N번째 DB로 옮겨주어야 함 (즉 rehash 작업이 필요)
  • 디비 개수가 늘어나거나 줄어들 때 Rehash를 해야 하는 총 레코드의 수가 10억개라면?
    10억개를 재배치하는데 걸리는 시간이 10시간이라면?
    총체적 서비스 불가 즉 장시간 점검 상태가 되어야 함
    일반적인 라이브 서비스에서 용납할 수 없는 시간
  • 클라는 인증 서버들 중 하나에 접속
    인증 서버는 매핑 디비에 query를 해서 대응하는 DB 인덱스를 얻음
    인증 서버는 해당 디비에 플레이어 관련 CRUD 쿼리 실행
    디비 증설 혹은 감소시, 기존 디비에서 원하는 만큼 유저 레코드를 증설된데로 옮기고 (안옮겨도 됨), 매핑 디비에서도 옮겨진 유저 레코드의 새 DB 인덱스로 갱신을 한다.
  • 매핑 디비가 죽으면 서비스 장애, 즉 매핑 디비가 SPOF (single point of failure)

  • 매핑 디비를 미러링하자
    많은 DB에는 비동기 replicate 기능이 있는데, 이를 사용하기
    혹은, DB를 여럿 두고 값을 기록할 때 여러 DB에 일제히 기록
    혹은, 비동기 replicate 기능이 주요 특징인 NoSQL (mongoDB, cassandra 등)를 사용
    클라는 인증 서버들 중 하나에 접속
    인증 서버는 매핑 디비 중 하나를 골라, 유저ID에 대응하는 디비#ID를 얻는 쿼리 실행
    인증 서버는 해당 DB에 CRUD 쿼리 실행
    매핑 디비가 비동기 미러링되는 경우, 간발의 차이로 옛날 데이터가 나와서 ‘그러한 유저 없음’ 오류가 나올 수 있는데, 이때는 로그인 처리를 몇 초 후 재시도하도록 하자.
  • 인증 서버는 보안 통신으로 게임 클라이언트에게 credential (ID, PW 대신 유저를 식별하기 위한 비밀 난수)를 보내주자
    클라이언트는 이후부터 credential을 보내도 유저 인증이 될 수 있음
    클라이언트가 다른 서버B에 ID,PW를 안 보내고도 로그인 하기 위해,
    인증 서버는 서버 B에게 {credential, 유저ID} 값을 보내주도록 하자
    클라이언트가 서버 B에 접속 후 credential을 암호화된 메시지로 보내면, 서버 B에서는 이미 credential을 갖고 있으므로 클라이언트가 누구인지 식별할 수 있음
    Credential 전달을 위해 인증 서버와 다른 서버간 통신을 할 수 있어야 함
    참고: 프라우드넷에는 서버간 통신 기능과 클라-서버간 암호화 메시징 기능이 있음

  • 게임 규칙
    게임을 시작하려면 10명의 플레이어가 게임방에 들어가야 함
    매치메이킹 처리
    게임을 플레이하고자 하는 플레이어는 게임 시작하기를 누르고 대기
    플레이어와 비슷한 실력을 가진 다른 플레이어 9명이 게임 시작하기를 누르게 되면 더 이상 대기 중지
    실력을 판단하는 근거로 ELO 레이팅 시스템이 사용되기도 함
    그리고 10명의 플레이어들이 플레이 가능한 게임방을 만들기
    게임방에서 플레이어들이 채팅을 하고 팀 결성을 한 후에 게임을 시작
    게임방 처리
    게임방에서는 플레이어들의 메시지를 받아 처리하고, 게임방 내에서 게임 월드 시뮬레이션을 실행

  • 서버 1개가 매치메이킹과 게임방 처리를 모두 담당해야 함
    동시접속자가 늘어날 때 과부하 지점
    게임방 내 월드 시뮬레이션을 위한 서버 CPU 과부하
    매치메이킹에 동시접속자가 너무 많이 들어갈 경우 서버 CPU, RAM 사용량 과부하

  • 과부하 지점: 게임방 처리
    매치메이킹을 위한 연산량보다 게임방 내 월드 시뮬레이션과 대량의 네트워크 메시지 처리를 하는 연산량이 훨씬 상회함
    데이터 응집도를 확인하면
    게임방 하나 내에서 플레이어들은 잦은 상호작용을 수행
    즉, 게임방 내 플레이어끼리의 데이터 응집력은 높으며, 서로 다른 게임방의 플레이어끼리는 응집력이 없음
    따라서 게임 서버로부터 게임방 처리를 여러 서버로 분산하자
    게임 서버는 1개의 로비 서버(매치메이킹 담당)과 여러 개의 배틀 서버(게임방 처리 담당)을 수행
  • 클라이언트는 매치메이킹을 하는 동안에는 로비 서버에 접속을 유지
    매치메이킹이 완료되어 게임방을 만들 때 가장 접속자가 적은 배틀 서버에 접속 (이때 매치메이킹 서버와의 연결을 끊는 것을 권장)
    게임방에서 게임을 즐기고, 게임이 끝난 후에 클라이언트는 다시 매치메이킹을 하기 위해 로비 서버로 돌아옴

  • 또다른 과부하 지점이 여전히 존재
    동시접속자가 늘어날수록 로비 서버가 과부하에 걸릴 수 있음

  • 매치메이킹의 루틴을 살펴보자
    매치메이킹을 위해 필요한 데이터는, 게임 시작을 눌러서 대기중이며 ELO 점수가 비슷한 다른 플레이어들의 목록
    로비 서버가 여러대로 나뉘어 있을 경우, 이 플레이어의 목록을 어떻게 액세스할 것인가?
    서로 다른 서버간의 상호작용 구현 3가지를 검토해보면
    동기 분산 처리  다른 서버의 플레이어 목록을 뒤지는 데 너무 많은 메시징이 발생함
    비동기 분산 처리  우측 if 구문 자체가 구현 불가능
    따라서, 데이터 복제에 기반한 로컬 처리가 불가피
  • 로비 서버를 여러대를 두자
    클라이언트는 로비 서버 중 하나를 아무나 골라 그 안에 접속을 하도록 하자.
    플레이어 목록을 모든 로비 서버들이 네트워크 동기화하자.
    단, 전부는 하지 말고, 플레이어 목록 중 게임 시작을 눌러 매체메이킹을 기다리는 것들만 동기화하자
    게임 시작을 누르면다른 로비 서버에게 플레이어 정보 전달
    게임 시작 취소를 누르면다른 로비 서버에게 플레이어 정보 사라짐을 전달
    플레이어 목록에는 플레이어가 어느 로비 서버에 있는지에 대한 정보도 같이 있어야 함
    그래야 게임방 시작을 할때 해당 플레이어의 로비 서버에게 메시지를 보낼 수 있으니까
  • 매치메이킹 조건을 만족하면(10개 비슷한 실력자들이 서버 내 플레이어 목록에서 발견됨) 각 플레이어들이 있는 로비 서버들에게 어느 배틀 서버로 접속해야 하는지를 알려주기
    같은 플레이어 그룹에 대한 게임 시작 처리를 동시에 진행하면 안되므로, 10개 플레이어 중 가장 작은 ID값을 가진 플레이어가 로그온된 서버에서만 게임 시작 결정을 하자.



  • 로비 서버간 플레이어 목록 동기화 과정에서 발생하는 데이터 불일치 문제가 발생 가능
    매치메이킹을 했으나 정작 그들을 게임방 만들어 들어가게 했더니 플레이어 하나가 이미 로비 서버에서 나간 경우
    자동 매치메이킹 재시작을 하게 하면 간단히 해결
    플레이어 입장에서는 매치메이킹이 좀 더 시간이 걸리는 정도로만 인식됨
  • 하나 하나 짚어가면서 설명하자.
  • 라이브 서비스를 위한 게임 서버 구성

    1. 1. 라이브 서비스를 위한 게임 서버 구성 넷텐션 배현직
    2. 2. 분산 서버를 구성할 때 지침 • 분산 서버의 이유: 확장성 • 서버 과부하 지점: CPU, RAM, Storage, Network • 부하 지점을 정확히 찾은 후 해당 부분을 처리 분산해야 • 데이터 분산을 우선으로 • 기능적 분산은 불가피할 때만 해야 • 낮은 응집력의 데이터가 분산 권장 대상 • 분산 처리는 단위 처리 성능과 디버깅에서 불리
    3. 3. 로그온 처리의 분산
    4. 4. 분산하기 전의 서버 클라 인증 서버 유저 DB
    5. 5. 과부하 지점
    6. 6. 인증 서버를 여럿으로 나누기 클라 인증 서버 유저 DB 인증 서버 인증 서버 인증 서버 클라
    7. 7. 여전히 갖고 있는 문제점 클라 인증 서버 유저 DB 인증 서버 인증 서버 인증 서버 클라
    8. 8. 디비 서버를 여럿으로 나누기 클라 인증 서버 유저 DB #1 인증 서버 인증 서버 인증 서버 클라 유저 DB #0 유저 DB #2 ID=홍길동 PW=??? ID=강부자 PW=??? Hash(홍길동,3)=0 Hash(강부자,3)=1
    9. 9. 여전히 갖고 있는 문제점 클라 인증 서버 유저 DB #1 인증 서버 인증 서버 인증 서버 클라 유저 DB #0 유저 DB #2
    10. 10. 유저 ID – DB #ID 매핑 서버 두기 클라 인증 서버 유저 DB 인증 서버 인증 서버 인증 서버 클라 유저 DB 유저 DB 매핑 DB 1. SELECT INDEX WHERE ID=XXX 2. INDEX가 가리키는 DB에 CRUD 실행
    11. 11. 여전히 갖고 있는 문제점 클라 인증 서버 유저 DB 인증 서버 인증 서버 인증 서버 클라 유저 DB 유저 DB 매핑 DB
    12. 12. 매핑 디비를 미러링하자 매핑 DB 매핑 DB
    13. 13. 인증을 마치고 나면
    14. 14. 매치메이킹의 분산 처리
    15. 15. Use case를 분석해보자
    16. 16. 분산하지 않은 서버의 경우 Match make + game room Client Client Client Client
    17. 17. 게임방 처리를 분산하자 Lobby server Client Client Client Client Battle server Battle server
    18. 18. 게임방 처리가 분산된 후 상호작용
    19. 19. 여전히 갖고 있는 문제점 Lobby server Client Client Client Battle server Battle server Client
    20. 20. 로비 서버를 분산 처리하기 전에 Match(player) { var list; for each (p in players) { if (p != player && p.waitingForGame && SimilarTo(player.elo, p.elo) { list.add(p); } } if(list.count == 9) { StartGameRoom(list); } }
    21. 21. 로비 서버 분산하기 Lobby server 1 Lobby server 2 Lobby server 3 Player A is waiting for game
    22. 22. Stale! (뒷북 둥둥둥) 다시 해보자 성공
    23. 23. 전체적 구성 Login Server Login Server Farm Server Lobby Server Lobby Server Battle Server Battle Server DB cache server DB cache server DB cache server DB DB DB Index DB NetClient DbCacheClient NetServer NetClient DbCacheClient NetServer NetClient DbCacheClient NetServer NetClient DbCacheClient NetServer NetClient DbCacheClient NetServer NetClient DbCacheClient NetServer NetServer DbCacheServer NetClient DbCacheServer NetClient DbCacheServer NetClient MS SQL or MySQL MS SQL or MySQL MS SQL or MySQL MS SQL MySQL NoSQL
    24. 24. 요약 • 분산 서버를 구성할 때 다음과 같이 진행을 하자 • 단일 서버로 만들었을 때의 구성을 먼저 그려보자 • 이때 예상되는 과부하 지점을 찾아내자 (혹은 직접 실행 후 측정으로) • 데이터간 응집력이 없는 경계를 찾자 • 과부하 지점을 데이터 분산 (3가지 방법론) 혹은 기능적 분산 중 택 일하자 • 배보다 배꼽이 큰 상황(내부 연산 < 메시징 처리)이 발생할 수 있는 지 고려하자 • 잘 모르겠으면 프라우드넷을 사서 쓰면서 넷텐션에게 분산 서버 구 성 자문을 받으시면(…) 됩니다.

    ×