The seamless load balancer.

PikkoServer를 이용하면  한층 쉽고 빠르게 MMO 를 제작할 수 있으며, 더 많은 플레이어를 수용할 수 있습니다.

라이선스 문의

Overview.

PikkoServer는 기존의 엔진 기술을 사용하여 대규모의 MMO를 제작할 수 있도록 지원하는 서버입니다. PikkoServer는 로드 밸런서의 역할을 맡아, 단일 서버용 아키텍처를 여러대의 분산된 서버에서 동작하게 하여 더 많은 유저들을 수용할 수 있게 합니다. PikkoServer는 태생부터 엔진과 비종속적이며 사실상 어떤 엔진과도 통합될 수 있습니다. 현재는 Unity엔진과 함께 작동하도록 되어 있으나 모든 종류의 멀티 플레이어 엔진을 매끄럽고 끊이지 않는 MMO엔진으로 변환시켜줄 수 있습니다.

Workflow.

PikkoServer를 사용한 게임 개발은 복합화된 엔진만을 사용한 개발과 동일한 환경입니다. 서버 개발자는 PikkoServer와의 통신을 위한 간단한 API를 구현하는 것만으로 PikkoServer의 로드 밸런싱, 오프젝트 분산배치, 서버간 핸드오버등을 사용할 수 있습니다. 이로써 서버 개발자의 업무가 매우 간단해집니다. 엔진의 네트워크 인프라가 그대로 재사용되기 때문에 클라이언트에서의 작업량은 이보다도 더 작습니다.

PikkoServer는 서버사이드의 수평적 확장(horizontal scalability)을 제공합니다.

게임개발사가 싱글 스레드로 프로그래밍된 서버 코드만으로 멀티코어 아키텍쳐를 사용할수 있게 함으로써 개발을 단순화하고 개발 시간을 단축시켜줍니다. 서버사이드는 여러대의 분산된 서버형태로 동작하며 네트워크 트래픽은 PikkoServer에 의해 분산처리 됩니다. 기술 요약문서와  확장성문서를 참고 하시면 더 자세한 정보를 얻으실 수 있습니다.

Game tick & bandwidth.

PikkoServer를 사용한다면, 최대 유저수 제한은 대역폭과 게임플레이가 네트워크를 얼마나 잘 지원하는지에 달려있습니다. 참고로 살펴볼 저희의 월드 레코드 게임에서는 가까운 오브젝트는 초당 15번, 먼 오브젝트는 초당 최대 3번까지 업데이트를 전송합니다. 각 클라이언트당 최대 다운로드는 20 KB/s으로 제한되었습니다. 이 방식으로 클라이언트는 999 명의 다른 유저를 손쉽게 처리할 수 있었습니다.

게임 디자인과 시나리오별로 요구되는 네크워크 사양은 각기 다릅니다. 월드 레코드 게임은 게임 디자인은 단순하지만 상당한 트래픽 관리를 요구하는 게임입니다. 다른 게임 디자인들은 통신 형태가 다르므로 다른 트래픽 패턴을 요구할 것입니다. PikkoServer는 많은 형태의 시나리오들을 처리할 수 있도록 설정이 가능합니다.

Game design limitations.

게임 플레이 디자인에 따라 서버 사이드의 병목현상은 대역폭이 될수도 있고 CPU가 될 수도 있습니다. 수평 확장 문서에는 여러가지 시나리오와 그에 따른 제한들이 기술되어 있습니다. 대부분의 경우 PikkoServer는 대역폭의 제한이 걸린 게임과 CPU 제한이 걸린 게임을 모두 커버할 수 있습니다.

네트워크 게임의 통신 패턴을 좀더 쉽게 연구하기 위해 우리는 메세지 타입을 두가지 종류로 분류했습니다. 메세지는 직접, 그리고 간접메세지로 나뉘며 또한 연속적 메세지와 불연속 메세지로 나누어집니다.

  1. 직접 통신 - 수신자가 명확한 통신입니다.
  2. 간접 통신 - 수신자가 명시되지 않은, 예를 들면 빌보드와 같이 원하는 누구에게나 열려있는 통신을 말합니다.
  3. 불연속 통신 - 아이템의 구매와 같이 연속되지 않은 이벤트로써 수신자는 내가 될수도 있고 아닐 수도 있습니다.
  4. 연속적 통신 - 소문이나 루머처러 끊임없이 계속되는 메시지로써, 새로운 정보가 예전 정보를 대체하는 형태입니다.

일반적으로 오프젝트는 간접 정보를 수신하기 위해서 특정 장소에서 특정 타입의 이벤트를 구독(subscribe)합니다. 특정 타입의 간접 정보를 서버에 요청할 수도 있습니다. 메세지 타입은 각기 4가지 패턴으로 지정될 수 있습니다.

일반적인 메세지 타입은 아래와 같습니다.

  1. 직접-불연속 – 멀티캐스트: 채팅 메세지, 교환(트레이딩), 오브젝트 생성/파괴
  2. 간접-불연속 – 방송(브로드캐스트): 시각적 효과, 청각적 효과, 총기사용, 미사일 발사등
  3. 직접-연속 – 멀티캐스트: 파티정보 – 보통 낮은 빈도수로 발생
  4. 간접-연속 – 브로드캐스트: 캐릭터의 위치 및 상태. 보통 높은 혹은 아주 높은 빈도수로 발생. 예를 들어 오브젝트 하나, 그리고 틱 하나당 한 번 발생하는 경우가 있으며 이런 경우 정보가 발신되기도 전에 이미 다른 정보로 대체될 수 있음.

이런 패턴들은 PikkoServer에 의해 각기 다른 필터에 적용됩니다. 일반적인 필터링 설정은 아래와 같습니다.

  1. 직접-불연속 – 이 패턴은 필터링이 되지 않기 때문에 잦은 사용은 피하시는 것이 좋습니다. 확장을 용이하게 하기 위해선 이 타입의 브로드캐스팅을 분당 특정 숫자 이하로 제한하는 것이 좋습니다.
  2. 간접-불연속 – 유저가 많을경우 모든 유저에게 전달되지 않을수도 있습니다. 메세지 타입별로 각기 다른 우선권이 부여될 수 있습니다.
  3. 직접-연속 – 전달됩니다만 바로 전달되지는 않을 수도 있습니다.
  4. 간접-연속 – 전달됩니다만 바로 전달되지는 않을 수도 있습니다.

모든 사람이 메세지를 받을 수 있도록 보장하는 브로드캐스팅은 직접-불연속 브로드캐스팅 뿐이라는 점을 참고하세요. 연속 타입의 브로드캐스팅은 모든 사람에게 전달되지는 않을 수도 있습니다.

영속적 통신 – 데이터베이스를 통하여 전달되는 통신들이 있습니다. 이런 타입의 통신들 역시 위의 패턴들로 분류될수 있습니다. 다만 용이한 필터링을 위해 특정 메세지 타입으로 정의됩니다. 즉, 영속적인 메세지 타입도 그 패턴에 따라 여타 다른 메세지 들과 같은 필터링을 거치게 됩니다.

만약 게임 디자인이 많은 양의 트래픽을 연속적, 혹은 간접-불연속적으로 허용해야 한다면 PikkoServer는 필터에 우선권을 지정하도록 할 수 있습니다.

Zones.

존이란 하나의 월드를 이루는 여러대의 셀 서버들로 이루어져 있습니다. 심리스 바운더리 없이 여러 지역을 커버하거나 평행하는 인스턴스들에서 같은 한 지역을 커버하기 위해 다수의 존들이 생성될 수 있습니다.

Zone sizes.

각 존의 면적은 클라이언트의 물리 엔진에 의해 좌우됩니다. PikkoServer는 자체적인 존의 면적 제한을 가지고 있지 않아 대형의 지역을 커버하는 좌표들을 처리할 수 있습니다.

Recovery of cell servers.

만약 특정 존을 처리하는 모든 셀서버에 부하가 걸리는 상황이 발생했을때 빠른 복구만큼 중요한 요소는 없을 것 입니다. 그런 상황에서 메세지 수신은 메세지 전송만큼 중요하지 않습니다. 해당 존에서의 클라이언트와 서버 틱을 모두 늦춤으로써 이런 상황을 벗어날 수도 있지만 PikkoServer 는 더 많은 셀서버를 실시간으로 투입함으로써 픽타임에서 부하를 해결하는 방법을 제공합니다. 셀서버의 추가와 제거는 수동, 그리고 모니터링 툴을 통한 자동화가 모두 가능합니다.

Hardware setup.

피코서버의 아키텍쳐는 모든 종류의 하드웨어 조합을 지원하며 대부분 속도와 비용의 문제일 뿐입니다. 만약 랙(Latency)을 최소화 하길 원하신다면 20-50 코어를 가진 현대식 하드웨어에 PikkoServer와 10~40개의 셀 서버를 설치하십시요. 이 셋업은 낮은 랙을 필요로 하는 인구밀집형 MMO에서 사용하는 매우 강력한 셋업입니다. 서버 비용이 우선시 된다면 8코어 서버에 PikkoServer를 설치한후 셀서버들이 설치된 4~8 코어 블레이드 서버와 Gigabit 랜 스위치로 연결하십시요. 이런 분산된 조합에서 발생하는 추가적인 랙은 몇 밀리세컨드(ms) 정도입니다.

Trading.

“경매장”을 통한 트레이딩은 일반적으로 데이터베이스 이슈입니다. PikkoServer는 특정 데이터베이스에 종속적이지 않기 때문에 퍼포먼스는 온전히 사용된 데이터베이스의 종류와 데이터베이스 개발/관리자의 몫입니다. 저희는 Riak 과 같이 확장 가능한 현대식 데이터베이스를 권장하며, 게임 개발용으로 개조된 Unity용 Riak클라이언트인 uGameDB를 개발했습니다. uGameDB에 대한 자세한 정보는 여기를 참고하세요.

인접한 아바타와의 트레이드는 여타 다른 상호작용(interaction)과 동일하게 처리되며 PikkoServer는 이에 대해 특별한 제한을 가지고 있지 않습니다.

Zone-to-zone transfers.

존(zone)간 전송 메커니즘은 매우 까다롭습니다. MuchDifferent는 PikkoServer와 몇대의 셀 서버로 구성된 존(zone)간에 초당 300건의 유저 전송을 처리할 수 있는 메커니즘을 구현했습니다. 또한 PikkoServer는 존의 개수의 제한이 없습니다. 존간 전송은 셀간 전송과 다소 혼돈 될 수 있습니다. “핸드오버”라 불리는 셀간 전송은 심리스하며 존간 전송보다 훨신 더 빠릅니다.

Zone management - the Mast algorithm.

PikkoServer는 무선 통신망에서 각 셀서버가 커버해야 할 지역을 산정하는 방식과 매우 흡사한 모델로 동작합니다. 무선 통신망에서 휴대폰은 항상 가장 물리적으로 근접한 마스트(기둥)과 연결되어 있으며 이동시 자동으로 다른 기둥으로 연결됩니다. 셀서버도 이와 동일한 원칙으로 동작합니다. 각 셀서버는 PikkoServer에 의해 가상 세계의 “마스트”에 할당되며, 유저나 게임 오프젝트는 서버에 의해 가장 가까운 마스트에서 처리됩니다. 연결된 마스트에서 멀어지게 되면 자동으로 서버에 의해 다음 가까운 마스트로 연결됩니다.

각 존에서 셀서버가 처리하는 지역은 정적이지 않고 존의 현 상태에 맞추어 계속해서 (매끄러운 처리를 위해 초당 5번정도 순차적으로) 변경됩니다.  PikkoServer는 존에서 마스트들의 위치를 계속해서 변경하여 각 셀 서버가 처리해야 하는 유저의 숫자를 균등하게 조절합니다. 이런 마스트의 동적인 성질은 게임의 상태에 맞추어 빠르게 적응할 수 있는 유연하고 확장성있는 아키텍쳐를 가능하게 합니다.

마스트가 빠르게 위치를 변경할 수 있게 하기 위해서 각 존을 담당하는 셀서버들은 게임내내 존 전체를 메모리에 로딩하고 있어야 합니다. 이렇게 함으로써 맡은 존의 위치가 바뀌더라도 항상 같은 퍼포먼스를 낼 수 있고 어느지역에서 넘어오는 유저라도 처리할 수 있습니다. 물론 유저가 있는 특정 지역만을 로딩하고, 유저들의 움직임에 맞추어 동적으로 로딩하는 것도 가능합니다.

Scaling handovers.

핸드오버(오브젝트가 한 셀에서 다른 셀로 이동하는 것)의 양은 게임의 이동 패턴에 따라 달라집니다. 셀서버는 핸드오버와 셀간 통신을 최소화 하기 위해 이 이동을 따라가려 시도할 것입니다. 게임 패턴에 따라 핸드오버나 셀간 통신이 확장하는 양이 달라진다는 것을 아는 것은 중요합니다. 예를 들어 우리는 월드 레코드 게임에서 유저의 밀도가 핸드오버에 미치는 양을 조사하기 위해 아래와 같은 로드 테스팅 스트립트를 작성했습니다.

1) 2D 공간에서 가로세로비는 1:1로 설정

2) 999 명의 인공지능 플레이어와 1명의 관찰자

3) 모든 플레이어는 동일한 속도로 랜덤하게 움직이도록 설정

4)모든 플레이어는 전체 맵에서 고르게 배치.

 

3번과 4번은 셀 서버가 특정 그룹을 따라다니지 못하도록 하는 설정입니다.

5) 셀 공간은 같은 크기로 고르게 분포되었으며 움직이지 않음.

이제 이 2D 그리드에서 위와같은 설정을 분석해 보도록 하겠습니다. 기본 유닛은 1m로 합니다 (3D 스페이스에서도 같은 유닛을 사용합니다)

N을 플레이어의 숫자라고 놓고 A 를 플레이 공간의 크기로 놓으면,

플레이 공간안에서 밀도인 ρ 를 위와 같이 구할 수 있습니다. 또한 같은 크기인 8개 셀로 이루어진 플레이 공간 안에서 셀 사이 테두리의 총 둘레는 아래와 같습니다.

.

이제 ṽ를 플레이어의 평균 속도로 놓습니다.

평면위의 모든 움직임이 고르게 분포되었다고 가정했을때, 우리는 한방향에서 테두리와 직각을 이루는 평균 속도를 아래와 같이 계산 할 수 있습니다.

한 방향에서 초당 테두리를 넘어가는 플레이어의 수는 아래와 같으며

.

테두리는 양쪽 방향에서 넘어갈 수 있기 때문에 전체 테두리의 길이를 아래와 같이 구할 수 있습니다.

.

이제 초당 핸드오버의 총합을 구할 수 있습니다.

H, B, ρ 는 A의 함수이기 때문에 이 등식을 이용해 플레이 공간의 사이즈와 플레이어의 밀도에 따른 핸드오버의 숫자를 아래와 같이 계산 할 수 있습니다.

.

이것을 토대로 ρ  함수인 H 구할  있습니다.

.

요약하면 아래와 같습니다.

.

비슷한 설정으로 3D 환경에서 계산해보면 아래와 같은 결과를 얻을  있습니다.

.

, 해당 설정에서 핸드오버의 수치는 플레이어 밀도의 스퀘어 루트 만큼씩 늘어나며 유사한 3D 설정에서는 큐빅 루트만큼 늘어난다는 것을   있습니다. 아래는 월드 레코드 게임에서 플레이 가능한 공간과 플레이어 밀도와의 관계를 나타내  것입니다.

저희가 Octave용으로 제작한 handoverdensity.m스크립트로 직접 테스트  보시기 바랍니다.

이것을 보여주기 위해 1000 명의 플레이어가 센터로 몰려드는 상황을 실험해 기록해 보았습니다. 이 실험을 통해 플레이 공간을 2% 수치만큼 줄여도 클라이언트에 요구되는 데이터 스트림의 속도는 일정하다는 것을 확인했습니다: 천명의 클라이언트가 중앙으로 모이는 실험비디오 (많은 폭발로 인해 카메라가 흔들리니 주의).

Client side limitations.

클라이언트 측면에서의 제한은 크게 두가지로 나누어집니다: 첫째는 많은 숫자의 오브젝트를 물리적으로 시뮬레이트 하는 것이고 (CPU 병목현상을 유발합니다), 둘째는 많은 숫자의 오브젝트 및 시각적 효과(Visual effect)를 동시에 렌더링 하는 것입니다 (GPU 병목현상을 유발합니다). 클라이언트쪽에서 많은 수의 움직이는 오브젝트와 효과를 애니메이션과 함께 처리하기 위한 최적화 방법은 여러가지가 있습니다. 몇가지 예를 보여드리기 위해 이와같은 클라이언트 부하를 월드 레코드 게임에 추가해 보았습니다. 비디오 데모를 곧 보실 수 있습니다.

클라이언트가 대형의 심리스한 게임세계를 처리함에 있어서 물리엔진이 2배 정밀도 부동 소수점(double precision floating point)을 처리할 수 있다면 도움이 됩니다. 이 기능 없이 문제를 해결할 수 있는 몇가지 트릭이 있긴 하지만 훨신 더 어렵습니다. 예를 들어 게임 맵이 10km 이고, 1배 정밀도 부동 소수점만을 처리할 수 있는 물리 엔진을 사용했다면 10km 덜어진 지점에서는1cm-정확도의 물리 계산만을 처리할 수 있습니다.

Server side limitations.

서버는 두 파트로 이루어져 있습니다. PikkoServer와 셀 서버(Cell Server)입니다. 우선 PikkoServer의 한계부터 알아보도록 하겠습니다. PikkoServer는 Erlang의 병렬처리능력을 최대한 사용하여 매우 확장성이 뛰어납니다. 그리고 PikkoServer가 네트워크 트래픽을 처리하는 레이어로써 작동할때 굉장히 복잡한 네트워크 최적화를 하기에 적합합니다. 저희의 스트리밍 제품 (고유 대역폭 최적화 모듈)과 함께 사용된다면 오브젝트의 시야, 게임플레이의 우선권, 클라이언트 대역폭의 반응속도에 따라 각 클라이언트별로 최적화된 패킷을 보내는 것도 가능합니다. 이러한 선택적 대역폭 제한과 트래픽 우선권 설정은 게임별 필요에 따라 개발자가 자유롭게 설정할 수 있습니다. 부하를 처리할 CPU가 모자를때에 PikkoServers는 낮은 우선순위의 아웃고잉(out going) 패킷을 드랍함과 동시에 아웃고잉 트래픽의 재전송률을 낮추기 시작합니다. 이 과정에서 유저는 랙(lag)이나 응답없음 상태를 경험할 수도 있습니다. 게임 틱(tick)을 늦추는 방법도 해결책이 될 수 있으나 이는 전적으로 게임 개발자의 구현에 달려있습니다. 그러나 PikkoServer는 이러한 피크 부하에서 최대한 빨른 복구를 우선 하도록 디자인 되어 있습니다. 참고로, 이러한 상황에서도 가장 심한 액션 상황에 노출된 클라이언들만이 영향을 받으며, 멀리 떨어진 다른 클라이언트들은 마치 아무일도 없던 것처럼 영향을 받지 않습니다. 이 부분에 대해서는 추후 다시 자세히 설명하도록 하겠습니다.

아키텍쳐의 또 다른 서버파트는 셀 서버들 입니다. 셀 서버군은 게임서버 코드를 가지고 있는 분산된 게임 서버들로 시스템을 이루고 있습니다. 셀 서버들은 물리, 데이터베이스 접속, 게임플레이 로직등을 처리합니다. 피크부하 상황에서 이들 서버의 동작방식은 큰 부분 게임플레이 프로그래머에 달려 있습니다. 핸드오버, 분산된 raycasting, 다수의 셀을 포함하는 광역 효과와 같은 셀간 커뮤니케이션은 셀서버의 부하에 큰 영향을 주지 않습니다. 대부분의 부하는 충돌 감지, 지역 raycasting, 데이터베이스 접속, 그리고 게임플레이 로직에서 발생합니다. 이것이 피크 타임의 서버 부하가 게임 디자인에 달려있는 이유입니다. 저희는 이러한 피크 상황의 부하를 처리하기 위해 추가적인 셀 서버의 투입을 권장합니다. 셀서버는 관리자에 의해 수동으로 추가/제거 될 수도 있고 Zone 제품과 같은 자동화된 모니터링 툴에 의해 제어될 수도 있습니다.

셀서버 구축을 위한 기본적인 가이드라인은 여기에 기술되어 있습니다.

Engine integration.

PikkoServer는 네트워크 프로토콜에서 동작하며 “중간자 공격”(MITM)과 흡사한 형태로 동작합니다. 이러한 아키텍쳐는 최소한의 게임 서버 수정만으로 어떤 엔진과도 통합될 수 있게 해 줍니다. 따라서 PikkoServer와의 복합화작업은 6개월 이상 소요되지 않을 것입니다.

Engine integration

Unity Game Engine

Unreal Engine (ongoing)

References

Technology overview

Scalability

Tank vs Robots in numbers

Unity integration

Video presentation 

Dev. partners

Unity Technologies

Epic

Uppsala University

SICS