Skynet 설계 설명

작자: cloudwu

번역: coolspeed

한달이란 시간에 걸쳐 드디어 skynet (https://github.com/cloudwu/skynet) 의 C 버전을 완성했다. 중간에 여러 모듈을 반복하여 리팩토링 한 결과 최종 남은 코드는 얼마 되지 않았다: 겨우 C 코드 6천여줄, 그리고 Lua 코드 천여줄이었다. 비록 일부 코드는 좀 급하게 짰지만 나 자신의 퀄리티 요구에 부합된다. 버그는 피면하기 어렵겠지만 이정도 작은 규모의 코드베이스는 충분히 명료하여 수정하기가 어렵지 않을 것이다.

Github 에 올린 이 프로젝트를 개발하는데 사용된 시간은 사실 한달도 훨씬 안된다. 나의 대부분 시간은 지난 반년 넘게 짜놓은 Erlang 버전 프레임워크와의 하위호환성과 호환 안되는 Erlang 모듈들을 포팅하는데 허비했다. 이 부분 코드들은 저희의 실 게임프로젝트와 관련 있는 것이어서 오픈하지 않았다. 또한 양이 이보다 몇배나 되는 관련코드들을 왕창 올려봤자 이 오픈소스프로젝트의 의미에 도움이 되지 않을 것이다. 프로젝트에 관심을 가지는 친구들은 그런 별로 중요하지도 않고, 많은 인터페이스들이 레거시 부담으로 추하게 설계된 구조 때문에 오히려 미궁에 빠질 것이다.

저희의 구 프로젝트와 연동시켜 보고 포팅도 다 잘 됐음이 확인된 후에 나는 또 skynet 의 일부 밑층 설계를 수정했다. 안전한 포팅을 보장하는 전제하에서 최대한 개선을 함으로써 히스토리컬 레거시를 최소한으로 걺어지도록 힘썼다. 이런 수정들은 쉽지 않았지만 의미가 있다고 생각한다. 최근 내가 자세하게 생각을 굴린 성과들이다. 오늘의 이 블로그글에서 나는 이번 픽스된 버전을 토대로 설계 설명을 좀 기록하려고 한다. 추후 찾아보기에도 좋게.


Skynet 코어는 어떤 문제를 해결하는가

나는 우리의 게임 서버가 ( 하지만 skynet 이 게임서버에만 사용될 수 있는게 아니다) 충분히 멀티코어의 파워를 이용할 수 있기를 바라며 서로 다른 비즈니스 로직들을 서로 독립적인 실행환경속에서 협동적으로 작동시키기를 원한다. 최초에 나는 이런 실행 환경이 OS 의 프로세스이기를 바랬다. 하지만 후에 발견한건데 만약 우리가 임베디드 언어를 필연적으로 사용하게 된다면, 예를 들어서 Lua, 독립적인 OS 프로세스의 의미가 크지 않을 것이다. Lua State 는 이미 충분히 양호한 샌드박스 환경을 마련해주어 서로 다른 실행환경을 격리해줄 수 있었다. 뿐만아니라 멀티스레딩 방식은 상태 공유를 통해 데이터 교환을 더욱 효율적으로 할 수 있게 해준다. 그러면서 멀티스레딩이 흔히 비평받는 단점들, 이를테면 복잡한 스레드 락, 스레드 스케쥴링 등은 밑단의 규모를 가능껏 제한하고 설계를 최대한 간소화함으로써 최소한의 범위안으로 가두어둘 수 있다. 이런 입장에서 skynet 은 최종적으로 3000 줄 안되는 C 코드로 코어층을 구현했는데 이것은 코딩 좀만 할줄 아는 C 프로그래머라면 빠른 기간내에 이해하고 유지보수 할 수 있는 규모이다.

핵심기능차원에서 skynet 은 오직 한가지 문제만 해결한다:

하나의 규약에 부합되는 C 모듈을 다이나믹 라이브러리 ( so 파일) 로부터 가동시켜 영원히 겹치지 않는 (모듈이 꺼지더라도) 하나의 숫자 id 에 바인딩하여 handle 로 사용하는 것이다. 모듈은 서비스 (Service) 라 불리고 서비스들은 서로 자유롭게 메세지를 보낼 수 있다. 모듈은 skynet 프레임워크에 하나의 callback함수를 등록하여 그것으로 자기에게 보내온 메세지를 받는다. 모듈들은 모두 하나하나의 메세지에 의해 드리븐 되고 메세지가 오지 않을 때에는 펜딩되여있으며 CPU 자원 소모가 0이도록 보장된다. 자발 실행적인 로직이 필요하다면 skynet 시스템에서 제공하는 timeout 메세지를 이용하여 일정 시간마다 트리그 시킬 수 있다.

Continue reading

[퍼옴] Ndc2014 시즌 2 : 멀티쓰레드 프로그래밍이 왜 이리 힘드나요? (Lock-free에서 Transactional Memory까지)

웬만해서는 블로그에 퍼온 내용은 올리지 않을려고 했는데…

이건 올려야 해 ( __ __)\

NDC 2014 세션 키노트:

SlideShare 사이트 링크:

Continue reading

LMAX 거래소가 게임서버 아키텍쳐에 주는 계시 #2

부제: <거래엔진의 참조가치가 어느 정도인가?>

1편에서는 LMAX 아키텍쳐를 소개하고 (소개했다기에는 부끄러울 정도로 간략하게 소개하고) 그것을 성공 사례의 거울로 한번쯤 비추어보자고 말했습니다.

그럼 제기할 수 있는 한가지 자연스러운 질문은: 거래엔진이 뭐 게임 서버도 아닌데, 뭐 어뜨케 참조하잔 말야? 참조할 가치가 있냐? 가 되겠습니다.

제2편에서는 이 문제들을 대답하기 위해 노력을 해보겠습니다.

간단한 대답은 이렇게 되겠습니다: 그렇습니다, 다릅니다. 거래 엔진은 거래 엔진이고 게임 서버는 게임 서버겠죠?

하지만 게임 서버도 게임 서버와 다릅니다. 실시성에 대한 요구가 높은 게임 서버도 있고 실시성에 별로 요구가 없는 게임 서버도 있습니다. 오케이, 알겠습니다. 보다 의미있는 비교를 위하여 이 글에서는 “게임 서버” == “실시간 게임 서버” 로 한정하겠습니다. 그렇다고 하더라도 실시간 게임 서버가 다 같은 건 아니겠죠? 거래 엔진도 거래 엔진이라고 해서 다 같은게 아닙니다.

무엇보다 유사성을 논할 때 우리는 특성들의 집합을 두고 논해야 하는거지 그것이 뭐라고 “불리는가”에만 의뢰하여 유사성을 판단할 수는 없습니다.

그러면 문제는 아래와 같은 형태로 전환됩니다:

거래 엔진과 실시간 게임 서버는 어떤 면에서 유사하고 어떤 면에서 다를까요?

사실상 거래 엔진과 실시간 게임 서버는 많은 특성들을 공유하고 있습니다:

  • 1. 높은 스루풋을 희망한다. (그 단위는 업계에서 공인 되는 건 여러가지가 있지만 여기서는 “TPS”로 하겠습니다.)
  • 2. 레이턴시를 최소화 하고 싶어한다.

— 1 과 2 의 원인으로 양자는 모두 아래와 같은 특점들을 지니게 됩니다.

  • 3. socket 서버이다.
  • 4. 유상태(stateful) 아키텍쳐를 취한다. (모두 “DATABASE IS DEAD”란 화제에 휩쓸리기 좋은 예제이다. 취소선.)
  • 5. 서버가 request / response 모델로도 구현이 가능하지만 성능과 실시성을 높이기 위해서는 보통 서버에서 클라에 푸시하는 방식도 있기를 원한다.
  • 6. IO boundary. (게임 서버의 경우 CPU boundary 일 수 있는데 이는 뒤에서 논하겠다)

— 그리고 semantic 각도에서

  • 7. 리퀫에는 “술어”(predicate) 가 포함되는 경우가 허다하다.

이는 아래의 공통된 특성을 초래합니다:

  • 8. C / S 통신의 내용에는 RPC 가 많다.

— 그리고  Continue reading

LMAX 거래소가 게임서버 아키텍쳐에 주는 계시 #1

LMAX Exchange 란 무엇인가?

2010 년에 영국 런던에서 창립되였는데 첫 온라인 외환거래소라고 합니다. 영국에서 성장이 가장 빠른 핀테크 업체이기도 하답니다. [1] [2]

LMAX 거래소가 최근 기술영역에서 주목받게 된 이유는 LMAX 가 업계 최고 성능을 자랑하는 마켓 엔진 아키텍쳐를 발표했기 때문인데요, 도대체 얼마만큼의 성능이 되냐구요?

비교대상으로 우리가 익숙한 고성능 시스템을 살펴봅시다.

  1. VISA 는 평균 2,000 TPS 성능으로 돌고있다고 합니다. [3]
  2. NASDAQ 의 자료에 의하면 NASDAQ 의 전대 엔진의 성능은 10,000 TPS 였고 그때는 그걸로 자랑을 했었습니다. [4]
    지금의 NASDAQ 는 35,000 TPS 부하로 돌고있다는 것을 들은 적 있는데 출처는 찾지 못하겠습니다. 이건 그냥 그럴 수도 있겠거니 정도로 들어주시면 됩니다.
    현재 최신의 NASDAQ 마켓 엔진도 고성능 솔루션을 연구하여 백만 TPS 의 성능을 낼 수 있다고 합니다. [5]
  3. redis 의 set 성능은 100,000 TPS 입니다. pipeline 모드를 켜면 400,000 TPS 입니다. [9]

그건 그렇고 오늘 말하려고 하는 LMAX 의 스루풋 절대수치는 얼마인가요?
무려 600 만 TPS 에 이른다고 합니다. [8]

LMAX 를 알게 된 것은 Bitshares 를 통한 것인데요. [6] [7]  Continue reading