본문으로 바로가기
    반응형



    5개의 섹션으로 발표가 진행되었다. 5개의 섹션의 발표가 10분의 쉬는 시간 한번을 제외하고는 연달아 진행되었다. 대학교 때도 2시간 이상 연강을 들어본적이 없었는데.. 청중들중에서도 조는 사람들이 많이 보였다.


    Section 1. HTML5/Websockt으로 Pong 게임 만들기


    전체적인 강의 흐름은 이러했다. HTTP환경에서 멀티플레이 게임 구축이 어려운 이유, 구축을 하기 위한 기술들. 그리고 마지막으로 Websocket을 사용한 pong게임 구현으로 진행되었다.


    1. 웹 환경에서 멀티플레이 게임 구축이 어려운 이유
      1. HTTP
        1. 전이중 통신이 불가능하다. (웹은 클라에서 요청하면 서버에서 응답을 주는 방식)
        2. 서버에서 Push
      2. HTML
        1. Markup Laguage의 한계 (브라우저 마다 보여지는게 다르다.)
        2. DOM 조작의 한계 (마크업이 객체화되면 DOM이되고 이 DOM을 움직여서 게임을 표현하는 것은 한계가 있다.)
    2. 그러면 웹 환경에서 멀티플레이 게임을 구축하기 위한 기술은 뭐가 있느냐?
      1. Request/Response가 아닌 Server Push가 가능해야 한다.
        1. LongPolling
          1. 브라우저는 미리 서버에 미리 요청을 보낸다. 
          2. 그러며 서버는 Push(게임 이벤트 전달)해야될 때 응답값을 보낸다.
          3. 브라우저는 응답값을 받은 후, 또 Push를 받기 위해 요청을 보낸다.
        2. LongPolling 단점
          1. 통신 빈도가 늘어난다. Push를 받기 위해 매번 미리 요청을 보내야하기 때문에
          2. 통신 딜레이 발생. 서버는 Push를 하기 위해 브라우저의 요청을 기다려야 한다.
        3. WebSocket
          1. 전이중 방식 지원
          2. TCP
          3. HTTP를 사용하지 않음
          4. TLS를 사용한 암호화 지원 (HTTPS를 위한 암호화 기술과 같음)
          5. 대부분 웹서버에서 WebSocket을 지원한다.
          6. Spring, Flask, PHP 웹프레임워크에서도 지원한다.

    WebSocket의 Handshake 과정


    WebSocket API


    3. 브라우저(클라이언트) 렌더링은?

    a. HTML

    i. Markup Language

    ii. Layout 및 Layering의 어려움 (이미지 배치 자체가 어려움)

    iii. Sound등 멀티미디어 지원 미비

    iiii. 클라이언트에 데이터 저장 기능이 없다.

    b. HTML5 

    i. <canvas> 직접 '그릴' 수 있는 영역

    ii. <audio> mp3/ogg 등의 사운드 플레이 지원

    iii. local storage key/value 쌍을 클라이언트쪽에 저장 가능

    iiii. Background 작업 수행 가능

    iiiii. 문제는... Window API DC 처럼 사각형 하나를 그리기 위해서 많은 메소드 호출을 해야한다.

    c. Phaser

    i. 2D 게임 엔진 사용

    ii. 물리엔진, scene, 카메라 같이 cocos2d 유사 기능 제공

    4. Pong을 구현하기 위한 기술들

    a. 통신은 WebSocket을 사용하고, 서버는 Physon의 flask라는 웹서버 기술을 사용.

    b. 브라우저 HTML5 위에 Phaser를 사용하여 렌더링한다.


    5. 소스코드

    https://github.com/iFunFactory/pong-webscoket (webscoket ?)


    Section 2. 분산 환경을 위한 ORM 개발 경험 공유


    ORM이란 관계데이터베이스의 데이터를 객체지향데이터로 변환하는 프로그래밍 기법이다. 컨퍼런스 가기 전에 목차를 보고 ORM을 몰라서 공부를 하고 갔었다. 


    1. 주요기능
      1. SQL 처리 자동화
      2. 잠금
      3. 캐시
      4. 분산 환경에서 동일한 작동
    2. 전체적인 흐름은?
      1. JSON으로 클래스의 멤버변수와 타입을 지정한다.
      2. 객체를 위한 인터페이스가 자동생성되며, 객체를 위한 SQL문도 자동 생성된다. (코드 자동 생성 기술 사용)
      3. 자동생성된 인터페이스
        1. Create 객체 생성
        2. Fetch 객체 로딩 (DB, 잠금, 캐시 처리를 내부에서 수행)
        3. 어트리뷰트 Get, Set 함수

    3. 구현 : 비동기 IO

    오브젝트를 가져올 때마다 데이터베이스에 I/O 블록킹을 하면 많은 수의 스레드가 필요하게 된다. 그래서 오브젝트를 가져와야되는 경우 예외를 던지고 예외를 잡은 이벤트 처리 스레드에서 비동기 I/O요청을 한다. 비동기 I/O가 완료가 되면 다시 해당 이벤트가 재등록되며 실행되도록한다.

    4. 구현 : 캐시 

    데이터베이스의 I/O 처리비용을 줄이기 위해서 캐시를 사용한다.

    5. 구현 : 잠금

    a. 여러 이벤트에서 한 오브젝트를 동시 수정을 한다.

    b. 캐시에 로딩된 오브젝트는 Lock 의 불가능 하다. 

    c. 이벤트 동안 오브젝트를 잠금하는 기능이 필요하다.

    d. 데드락 발생

        1. 상호배제, 점유대기, 비선점, 순환대기 4가지 조건을 만족하면 데드락 발생
          1. 상호배제 : 프로세스들이 필요한 자원에 대해 배타적인 권한을 요청
          2. 점유대기 : 하나의 자원을 선점한 상태에서 다른 자원 대기
          3. 비선점 : 사용중인 자원을 뺏을 수 없다
          4. 순환대기 : 각 프로세스가 다른 프로세스가 필요하는 자원을 가지고 있다.

    e. 데드락 회피를 위한 방법

    i. 타이머 이용 - 점유대기 방지

    획득한 모든 자원을 해제하고 대기했다가 이벤트를 다시 등록

    ii. 선점형 잠금 - 비선점 방지 

    먼저 실행된 이벤트가 나중에 실행된 이벤트의 자원을 빼앗을 수 있다.

    6. 구현 : 분산환경 캐시와 잠금

    a. Zookeeper를 사용하여 오브젝트 소유권 관리

    i. 파일 시스템 처럼 사용. 경로를 지정하여 데이터를 지정

    ii. redis lock 처럼 사용하는 것 같다.

    b. objects/{object-id} 파일이 존재하면, 파일안에 저장된 오브젝트를 가지고 있는 서버정보를 가지고 해당 서버에 오브젝트를 요청하는 형식


    Section 3. Scalable한 게임서버 만들기


    5개의 섹션중에서 가장 관심이 있던 섹션이였다. 아무래도 서버개발자이다 보면 분산환경에서 서비스 제공을 많이 하게 된다. 하지만 정작 나는 개념만 알고 있지 그 이상은 심도 있게 알지도 못하고 있다. 그래서 더 관심이가고 기대되었던 섹션이였다.


    1. 늘어나는 유저를 어떻게 수용할 수 있을까?
      1. 효율성
      2. 동시성
      3. 분산시스템에서 작업 쪼개기
      4. 동적인 서버 추가/삭제
      5. DB관련 참견

    2. Scaleup 

    일반적으로 Scaleup은 HW의 확장을 말할 것이다. HW를 추가하면 기존의 소스코드 변경없이 간단한 포팅으로 성능 향상이 가능하다. 하지만 HW 상에도 한계가 존재하며, 어느 이상되면 비용이 급격하게 증가한다.


    SW를 개선해보자

    1. inefficiency 개선
      1. 더 나은 알고리즘을 사용한다.
      2. Busy-Waiting을 지양한다. 비동기 활용.
      3. Readability 의 중요성(갑자기..) Efficiency, Readability는 tradeoff 관계.
      4. Readability 는 코드의 가독성을 나타낸다. 코드가 읽기가 쉬워지면, 관리하기가 편하고 그러면 버그 발생이 줄어들고, 그러면 프로그램의 안정성까지 직결되는 중요한 요소이다.(공감..)

    2. concurrency

    a. More 스레드 혹은 프로세스(Remote) != More Concurreny

    b. 비동기를 사용 지향하며, 동기화지점을 줄여라. 

    c. 간섭과 의존성을 최소화해 Blocking을 피하는 것이 좋다.

    3. concurrency 핵심 : Shared Data 에 대한 접근 처리

    a. Pessimistic Concurrency  

    경합이 있을거라는 전제, Shared Data에 대한 배타적권한 획득, 프로그래밍 Lock, DBMS 의 Lock 

    b. Optimistic Concurrency

    경합이 드물거라는 전제, Shared Data를 일단 사용하고 업데이트 혹은 갱신되었으면 Rollback 하거나 Retry 



    c. pessimistic vs optimistic 


    pessimistic

    optimistic

    경쟁이 적을때동시성이 약함동시성을 잘 살림
    경쟁이 많을때진행이가능잦은 rollback과 retry로 진행이 불가능할 수 있음


    d. optimistic을 게임에 적용한다면

    소켓같은 빈번한 경쟁에서는 부적합하지만, 인던에서 아이템 줍기같인 경쟁이 적은 시스템에서 사용이 가능하다. 



    4. 분산시스템에서 작업 쪼개기

    a. domain-agnostic distribution

    작업서버들은 완전히 동일한 Instance, stateless 한 process unit. 웹서버가 scaling하는 것이라고 생각하면 된다.

    b. domain-specific distribution

    작업서버들은 각각 배정받은 역할을 실행, in-memory에 state 유지. 일반적으로 Zone서버나 로비서버등..



    c. 결론적으로 간섭과 의존성을 최소화해 Blocking을 피하는 것이 좋다. (Thread나  Process(Remote)나 같은 맥락)


    5. 동적인 서버 추가/삭제

    서버 등록용 외부 Registry를 사용한다. Zookeeper나 Reids 같은 서버

    저장 내용은 RPC(RemoteProcedureCall) endpoint, serve tag 정도

    6. DB관련 참견

    DB는 편리해서 많이 사용한다. DB는 컴퓨팅 코스팅이 비싼 요소이다. DB는 의도적으로 동기화 포인트를 계속만드는 것이다. 게임서비스 확장에 제한을 두는 점. DB보다 가벼운 캐시를 사용하던가. 게임서버상에서 분산 처리 한다. 


    결론 비효율성을 줄이고 동시성을 늘려라. 단일 프로그램이든 분산환경이든 동시성이 중요하다. 비동기처리를 하고 동기화지점은 최소화해라. 


    Section 4. 리눅스 게임서버 성능 분석


    1. eBPF란 무엇인가?

    커널수준에서 다양한 이벤트에서 데이터 수집을 하게 해준다. 시스템콜 혹은 커널함수

    수집한 데이터는 커널 메모리에 모을 수 있다.

     2. eBPF + BCC란 무엇인가?

    개발자가 필요로하는 CPU, 네트워크 스텍, 디스크 I/O, 메모리의 정보를 얻을 수 있다.

    측정 대상을 재시작할 필요 없이, eBPF + BCC만 수정하고 재시작하면 다시 측정할 수 있다.

    가설을 세우고 이를 확인할 수 있는 질문을 만든다 -> 답을 얻을 수 있는 eBPF + BCC 프로그램을 만든다. -> 돌고 있는 프로그램에서 이를 측정한다.

    3. eBPF, BCC

    eBPF는 리눅스 커널에 들어있는 트레이싱/디버깅 도구

    BCC 는 Python/Lua/Go 등에서 eBPF를 쓰기 위한 툴체인 



    할당한 후 해제하지 않은 메모치 찾기 (질문) -> 할당한 후 30분째 해제하지 않는 메모리에 대한 콜 스택 목록(답) -> eBPF에서 memleak 사용 -> memleak을 사용하여 결과값을 보여주는 eBPF + BCC(결과값 렌더링) 프로그램 생성 -> 측정  


    Section 5. 아이펀엔진과 데디케이트 서버로 멀티플레이 게임서버 구현하기


    이번 섹션은 아이펀엔진과 관련된 내용이라 우리 팀에서 공유할만한 내용이 없는 것 같다. 엔진소개하기전에 나온 몇가지 개념에 대해서 정리해보자 한다.


    1. 웹서버로 게임서버를 구현하면?

    a. 클라이언트의 요청을 서버가 처리하는 구조

    b. Stateless 서버

    c. 서버 확장이 용이함

    d. 문제점으로는 반 이중 방식(서버 푸시 불가능), DB 부하가 큼(Stateless 다 보니 DB 입출력이 잦음), 문자열 전송 방식(바이너리가 x)

    로드밸런싱 뒤로 게임서버, DB가 시스템으로 구성


    2. MMO 멀티플레이 게임 서버

    a. 전이중 통신을 지원해야 한다. (서버 이벤트 푸시 가능)

    b. Statefull 서버(In-Memory)

    c. 월드/지역 개념 사용. 지역, 월드내 유저간에 이벤트 전송


    3. 부하를 줄이기 위한 방법

    a. 서버를 기능적으로 분리 (채팅 서버, NPC서버 따로 만듬)

    b. 같은 서버를 여러개 사용하여 처리(지역서버)

    c. MO 형 컨텐츠를 섞는다. (인스턴스 던전, 뒤에설명)



    4. MO형 멀티플레이 게임서버

    a. 가상의 룸을 만들어 유저가 모이면 게임을 시작

    b. 룸 단위로 데이터 동기화 

    c. 데이터베이스 부하가 적음 (In-Memory처리, 주로 로비서버 데이터가 DB I/O가 잦음)



    5. 데드케이티드 게임 서버

    발표한 내용과 구글링에서의 개념이 좀 상이하다. 구글링의 경우 클라이언트-서버 구조로, 호스트 역할만 전담하는 시스템이 모든 사용자를 수용하는 형태라고 하는데. 발표에서는 클라이언트 엔진으로 구현한 게임서버라고 한다. 클라이언트를 서버모드로 실행하면 데디케이트 서버라고 말한다. 오버워치, 배틀그라운드가 이런 형식의 서버를 사용하고 있다고 한다.


    6. 아이펀엔진

    아이펀엔진에 대한 소개 및 사용방법 설명을 하였다. 엔진을 통해 로비서버 만드는법, 데디케이티드 게임서버 매니저를 사용해서 데디케이티드 서버 제어 하는 방법, 데디케이티드 서버 호스트 매니저를 통해서 데디케이티드 서버 호스트 자동확장 방법등을 설명하였다.




    정리하다보니 양이 방대한 것 같다. 이해 안되던 부분들도 다시 곱씹으니 하나하나 개념이 쌓여가는 것같다. 


    앞으로도 여유가 있다면 컨퍼런스를 참가해서 문서로 정리하여 공유하고 싶다. 이런 지식들이 모두 나의 자산이 될터이니..


    반응형