Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018

2,742 views

Published on

Published in: Technology
  • Visit this site: tinyurl.com/sexinarea and find sex in your area for one night)) You can find me on this site too)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Sex in your area for one night is there tinyurl.com/hotsexinarea Copy and paste link in your browser to visit a site)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Girls for sex are waiting for you https://bit.ly/2TQ8UAY
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Meetings for sex in your area are there: https://bit.ly/2TQ8UAY
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Best site for flirting and sex in your area you can find there: https://bit.ly/2SlcOnO
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018

  1. 1. 이승재 | 넥슨코리아 데브캣스튜디오 실버바인 서버엔진 2 설계 리뷰 1
  2. 2. 발표자: 이승재 카바티나 스토리 데스크탑 히어로즈 마비노기 2 마비노기 듀얼 실버바인 서버엔진 2 (2015~) @0xcafea1fa 2
  3. 3. 실버바인 서버 엔진? 게다가 2??? 3
  4. 4. 2014 ~ 2015 4
  5. 5. 실버바인 서버엔진 1을 소개합니다 C++/Lua 엔진 일부와 게임 로직 전체를 Lua로 작성 HTTP + 롱 폴링 빨리 만들기 위해 잘 알고있는 기술을 택함 MariaDB + Redis 특히 Redis를 대단히 복잡하게 사용함 2015 2016 5
  6. 6. 실버바인 서버엔진 1의 최우선 설계 목표 마비노기 듀얼을 빨 리 출 시 6
  7. 7. 설계 목표가 아니었던 것 다른 게임 만들기에 편할 것 엔진 코드와 게임 코드의 구분이 모호하다. 재사용할 수 있는 부분을 분리하는 데 상당한 시간이 필요하다. 다양한 장르 게임을 만들 수 있을 것 서버의 이벤트를 전달받는 지연시간이 길어서, 실시간 멀티플레이는 턴제 게임 이외의 것을 만들 수 없다. 장기적으로 유지보수성이 좋을 것 로직을 동적 타입 언어(Lua)로 만들었기 때문에 리팩토링이 고통스럽다. 테스트 빡빡하게 붙어있으니 할 수는 있지만… 7
  8. 8. 회고 최우선 설계 목표를 달성함. 다른 새 프로젝트에 적용하기에는 좋지 않다. 8
  9. 9. 2016 ~ 9
  10. 10. 새 서버엔진 개발 제안 10
  11. 11. 그 이후로 약 2년 실버바인 서버엔진 2를 사용해서, • 출시한 게임 1개 • 개발중인 게임 4개 • 프로토타이핑한 게임 3개 • 서비스한 웹사이트 1개 + 신규 프로젝트 (글로벌 유명 인기IP) + 신규 프로젝트 (캐주얼 퍼즐 게임) 11
  12. 12. 이 발표에서는 1. 실버바인 서버엔진 2를 통해서 어떤 문제를 해결하려 했는지, 2. 그런 문제들을 어떻게 해결했는지를 리뷰합니다. 12
  13. 13. 여행기 스크린샷:카카오내비 13 비슷한 고민을 해보신 분들께는 ‘그런 문제들을 그렇게 해결했구나’ 그렇지 않은 분들께는 ‘게임 서버 만들 때 이런 고민도 하게 되는구나’
  14. 14. 양해 부탁드립니다 1 실버바인 서버엔진 2의 설계 결정은, • 2016~2018년의 데브캣 스튜디오라는 특수성에 크게 의존할 수도 있습니다. • 상황이 변함에 따라, 그리고 경험을 쌓아감에 따라, 앞으로 설계 결정을 번복할지도 모릅니다. 이 발표에서는 현재 시점을 기준으로 이야기합니다. 14
  15. 15. 양해 부탁드립니다 2 분량이 매우 많습니다 빠르게 진행하겠습니다 15
  16. 16. 목차 • 시작 • 목표 • 선택 게임 로직 작성하는 언어 / 데이터베이스 • 설계 동시성 처리 / 데이터 저장 / 네트워킹 / 백오피스 • 의미 16
  17. 17. 목표 17
  18. 18. 목표를 어떻게 정의할까 엔진을 사용하는 게임이 성공한다 서버 엔진으로 게임이 성공하게 하려면? 서버 엔진으로 게임의 성공 확률을 높이려면? 18
  19. 19. 목표를 어떻게 정의할까 엔진을 사용하는 게임이 성공한다 많은 프로젝트 / 적은 리스크 / 적은 비용 / 유니크함 이 원칙들이 서버엔진 설계 전반에 영향을 미침 19
  20. 20. 더 많은 프로젝트가 이 엔진을 사용할 수 있게 한다 낮은 진입장벽 적은 제약 (주로 반응시간) 20
  21. 21. 서버가 성공을 방해할 요인을 가능한 한 제거한다 유저 데이터 보호 규모가변성 (Scalability) 내결함성 (Fault-tolerance) 21
  22. 22. 서버 개발 비용을 줄인다 서버가 완성되지 않아서 출시를 못 할 리스크를 줄인다. 더 많은 실험을 할 수 있고, 더 많은 피처를 넣을 수 있도록. 어느 게임에나 필요한 것들은 엔진에 이미 들어있어야 한다. 엔진을 사용하기 쉽고, 잘못 사용하기 어려워야 한다. 22
  23. 23. ‘잘못 사용하기 어렵게’ https://www.volvocars.com/kr/about/our-innovation-brands/intellisafe 23
  24. 24. 이 엔진을 사용했을 때만 가능한 무엇인가를 만든다 다른 게임에서 본 적 없는 것을 기술 주도로 프로토타이핑하고 그것으로부터 프로젝트가 생겨날 수도 있을 것이라 기대. 아직 이 단계는 아님. 24
  25. 25. 목표를 어떻게 정의할까 엔진을 사용하는 게임이 성공한다 많은 프로젝트 / 적은 리스크 / 적은 비용 / 유니크함 낮은 진입장벽 적은 제약 유저 데이터 보호 규모가변성 내결함성 풍부한 기능 사용하기 쉽게 잘못 사용하기 어렵게 지금은 곤란합니다 잠시만 >_< 25
  26. 26. 상대적으로 덜 중요한 가치 하드웨어 비용을 극한까지 최적화 절대로 죽지 않는 서비스 26
  27. 27. 가치가 상충할 때 결정은 어떻게? 동료의 의견을 듣고, 경험과 감으로 결정합니다. 27
  28. 28. 목차 • 시작 • 목표 • 선택 게임 로직 작성하는 언어 / 데이터베이스 • 설계 동시성 처리 / 데이터 저장 / 네트워킹 / 백오피스 • 의미 28
  29. 29. 선택: 게임 로직 작성하는 언어 29
  30. 30. 선택의 기준 스튜디오 프로그래머들이 익숙한 언어 중에서 고른다. 서버 엔진 도입 진입장벽을 낮추기 위해서. 후보는 C++, C#, Lua. 30
  31. 31. C++ 마비노기 2 클라이언트에 사용됨. 언리얼엔진과 언어를 맞출 수 있다. 메모리 세이프티가 없다. 빌드가 느리다 = 이터레이션이 느리다. 31
  32. 32. C# 마비노기 2 서버에 사용됨. 유니티와 언어를 맞출 수 있다. 32
  33. 33. Lua 마비노기 듀얼에 사용됨. Gideros와 언어를 맞출 수 있다. 프로그래머의 단순한 실수를 잡아주지 않는다. 정적 타입체크되는 루아 변종 언어를 만들어서 돌파하겠다고 계획함. 그리고 실제로 해냈습니다 33
  34. 34. 초기 결정 게임 로직 언어로 C#과 Lua를 지원하자. 클라이언트 유니티 → 서버 C# 클라이언트 Gideros → 서버 Lua 엔진의 공통 부분은 C++로 작성하자. 34
  35. 35. 현재 스튜디오에 Gideros 프로젝트가 더 이상 없다. 유니티와 언리얼로 통일됨. 프로토타이핑에는 또다른 도구를 쓴다. 엔진 API의 많은 부분을 C#으로 만들게 되었다. 언어 바뀌는 경계에서 프로그래밍하기 번거롭더라. 현재는 게임 로직 언어로 C#만 지원하고 있다. 35
  36. 36. 선택: 데이터베이스 36
  37. 37. 마비노기 듀얼 (2014~2015) MariaDB 시스템 엔지니어링 조직(현 모바일인프라실)의 권고에 따라 선택. 전체적인 DB 설계 가이드를 받음. Redis 잘 알고 있고, 서버간 통신에도 활용할 수 있어서 선택함. 디스크 저장 옵션을 켜고 중요한 정보도 저장했다. 롱 폴링과 PUB/SUB을 엮어서 멀티플레이를 구현했다. 37
  38. 38. 바꿀까? 단점이 없는 데이터베이스는 없다. 아마도. 뭘로 바꾸더라도 지뢰를 한번은 밟을 것이다. 지뢰가 어디 있는지 알고 피하는 것이 낫다. 바꾸지 않기로 결정. 38
  39. 39. 목차 • 시작 • 목표 • 선택 게임 로직 작성하는 언어 / 데이터베이스 • 설계 동시성 처리 / 데이터 저장 / 네트워킹 / 백오피스 • 의미 39
  40. 40. 설계: 동시성 처리 40
  41. 41. 동시성 처리 서버엔진 설계의 가장 핵심. 다른 모든 부분은 교체할 수 있지만 이것만은 교체할 수 없다. 동시성을 처리하는 방법이 같아야 조립해서 쓸 수 있다. 41
  42. 42. 문제: 서버에는 외부 시스템에 요청하고 결과를 기다려서 처리하는 일이 많다. • 예: DB 접근 한번에 하나씩만 처리한다면 • CPU는 결과를 기다리느라 대부분의 시간 동안 놀게 된다. • 1ms가 걸리는 일은 1초에 1,000번 할 수 있다. • 10ms가 걸리는 일은 1초에 100번 할 수 있다. 42
  43. 43. 동시성 처리 요청을 보내 놓고 나서 응답을 기다리고만 있지 말고 다른 작업을 처리해야 한다. 다르게 표현하면, • 기다림을 처리하는 방법 • 동시에 여러 일을 진행하는 방법 • 요청의 결과가 돌아왔을 때 원래 맥락을 되찾는 방법 43
  44. 44. 설계 선택지: 멀티스레드일 때 작업과 작업 사이에 메모리에 상태를 저장하는가? 메모리에 저장한 상태를 여러 스레드가 함께 변경하는가? 공유 자료구조의 접근을 어떻게 제어하는가? 예 아니오 예 아니오 비관적으로 낙관적으로 트랜잭셔널 메모리락 기반 멀티스레딩 액터 스테이트리스 44
  45. 45. 스테이트리스 마비노기 듀얼 서버가 이것. MMORPG를 만들기에는 반응시간이 너무 길다. 빠른 포기 45
  46. 46. 액터 – 허스키 익스프레스의 예 MMO 서버 개발 포스트모템: 마비노기에서 M2프로젝트까지 / 임태현 / NDC2012 / http://www.slideshare.net/devcatpublications/mmo-ndc2012 46
  47. 47. 액터 – 마비노기 2의 예 MMO 서버 개발 포스트모템: 마비노기에서 M2프로젝트까지 / 임태현 / NDC2012 / http://www.slideshare.net/devcatpublications/mmo-ndc2012 47
  48. 48. 액터 – 마비노기 2의 예 생산성 괜찮았던 것으로 기억함 사고 실험 • 다른 플레이어의 I/O 지연시간이 전염되겠다 • MO에는 괜찮으나 MMO는 곤란할 듯… 48
  49. 49. 트랜잭셔널 메모리 • DB처럼 메모리에 트랜잭션 걸고 커밋/롤백을 한다는 개념 • 10년쯤 전에 핫했는데… • 언제 오는거야 미래 49
  50. 50. 락 기반 멀티스레딩 너무 복잡하고, 실수하기 쉽다. • 락을 걸어야 하는데 빠뜨리기 • 락을 잡은 채로 I/O Wait하기 • 데드락 • 락 경합 50
  51. 51. 락 기반 멀티스레딩 게임 로직은 이미 너무 복잡하고 변동성이 높다. 로직 프로그래머에게 락 기반 멀티스레딩의 부담을 추가로 주는 것은 바람직하지 않다. 51
  52. 52. 꿈도 희망도 없나? 52
  53. 53. node.js 싱글스레드에서 여러 절차를 동시에 실행한다! 싱글스레드이므로 공유 자료구조 접근 제어가 훨씬 쉽다. 어떻게? • 요청 결과가 콜백으로 온다! 53
  54. 54. node.js: CALLBACK HELL 54
  55. 55. async/await 훨씬 편하고 튼튼하게 짤 수 있다 기존 싱글스레드 장점을 유지 • 여러 절차를 동시에 실행 + 공유 자료구조 접근 제어가 쉽다 TypeScript는 1.7부터 (2015.11) Node.js는 7.6부터 (2017.3) 55
  56. 56. 실은 매우 오래되었다 • Stackless Python (1998) • Game Programming Gems 2권 ‘게임 객체 AI를 위한 마이크로 스레드’ (2002) • Lua 5.0 coroutine (2003) • 마비노기 1 (2004년 출시) 56
  57. 57. C#은? async/await가 있다! C# Task 라이브러리는 await 지나고 나면 스레드가 바뀜 우리는 RunSynchronously를 사용해서 스레드를 강제 SynchronizationContext를 쓰면 된다는데 해보진 않음 57
  58. 58. CPU를 충분히 활용하지 못하지 않는가? 로직 스레드는 전혀 블로킹 없이 최대 속력으로 실행 더 많은 요청을 더 빠르게 처리하는게 중요하지, CPU를 바쁘게 만드는 게 중요한 게 아니다 I/O를 다른 스레드에서 실행 • 네트워킹 전담 스레드 있음 • DB/Redis 호출에 쓰는 스레드 수십 개 58
  59. 59. 로직 스레드가 병목이 되면? 한 인스턴스에 여러 프로세스를 띄우거나 vCPU 개수가 적은 클라우드 인스턴스를 여러 개 사용하면 된다 하나의 프로세스에 5천명씩 받는 건 못함. 59
  60. 60. 의외의 장점 AI/액션 코드를 이것을 활용해서 만들면 좋다. 마비노기 모바일에서 사용 중. 60
  61. 61. 동시성 처리 • 서버엔진 설계의 가장 핵심. • 다른 모든 부분은 교체할 수 있지만 이것만은 교체할 수 없다. • 동시성을 처리하는 방법이 같아야 조립해서 쓸 수 있다. 61
  62. 62. 동시성을 처리하는 방법이 다른 도구와 조립하는 방법 블록하는 호출 백그라운드 스레드에서 실행하고 돌아오기 다른 스레드로 가버린 ~Async() 메인 스레드에서 이어서 실행하기 62
  63. 63. 동시성 처리: 정리 • 게임 로직은 싱글스레드 • async/await을 갖고 파이버를 만들어서 사용 • I/O는 멀티스레드 • 다른 라이브러리는 어댑터를 붙여서 씀 63
  64. 64. 설계: 데이터 저장 64
  65. 65. 데이터 저장: 목차 • 주 저장소 • 보조 저장소 65
  66. 66. DB ~파멸편~ • 인덱스 안 걸린 컬럼으로 검색하는 것 막아야 한다. • WHERE 빼먹는 것 막아야 한다. • DB 스키마 맞추는 것 너무 번거롭고 오래 걸린다. • 유저 데이터 변경을 자동으로 기록하고 싶다. • 수평 확장을 게임 로직이 모르게 하고 싶다. • 한 트랜잭션에서 여러 DB를 변경하고 싶다. • DB 데드락 미리 방지하고 싶다. 66
  67. 67. 발상 엔진을 통해서만 DB에 접근하자. • SQL 테이블 정의는 어떤 게임이든 똑같다. • 데이터 형식을 자체 문법 파일로 작성하면 C# 코드가 자동 생성된다. • 로직 프로그래머가 직접 SQL 작성할 수 없다 67
  68. 68. 장점 장점! • SQL 배우지 않아도 된다. • DB 스키마가 소스코드에 있으니 맞추기 쉽다. • 인덱스 타지 않는 쿼리를 만드는 것이 불가능하다. • 수평 확장, 분산 트랜잭션, 변경 로그 작성을 엔진이 알아서 한다. • DB 데드락이 발생할 가능성이 있으면 엔진이 미리 알려준다. 68
  69. 69. 데이터 형식 포맷 Visual Studio 문법 강조 플러그인 : DH팀 박경남님 제작 69
  70. 70. DB에 저장할 때는 • 필드를 json으로 인코딩해서 저장하고 있다. • 더 타이트한 포맷으로 바꾸는 것 고려하고 있었으나 • 타 시스템과의 연동 때문에 놔둬야 할 듯;; 70
  71. 71. 데이터의 동시성 제어 비관적 동기화를 사용한다. 개별 작업의 반응시간은 크게 중요하지 않다. 드물게 발생하는 버그를 내지 않는 게 더 중요하다. 락 관련 문제는 엔진이 감지하고 경고한다. 락을 잡지 않고 읽는 문제. 미리 정의한 락 순서를 지키지 않는 문제. 71
  72. 72. 데이터 모델 락 기반 비관적 동기화 + 명시적인 락을 채택 게임 로직 프로그래머가 락을 의식하게 해야 한다 그럼 락의 단위는? 너무 작으면 프로그래밍하기 괴롭고 반응시간도 길어진다 너무 크면 동시성이 떨어진다 72
  73. 73. 락을 유저 단위로 잡자! 게임 데이터의 특징: 대체로 데이터가 한 유저에게 속해 있다. 길드 창고 같은 경우 길드를 가상의 유저로 볼 수 있다. 유저별로 DB 테이블들이 있는 것 같은 느낌을 주자! 유저를 일반화해서 엔진에서는 Document라고 부르고 있음. Document가 락 단위이기도 하다. 73
  74. 74. Global Table 특정 유저에게 속하지 않은 데이터를 저장할 수 있어야 한다. • Key-Value 테이블을 제공한다. • Global Table이라고 부름. • Key가 락 단위가 된다. 74
  75. 75. Document의 수평 확장 한 Document는 같은 DB에 넣는다. 어느 Document가 어느 DB에 들어있는지 별도 테이블로 관리. 변경되지 않으므로 공격적으로 캐싱할 수 있다. 라이브 추가도 가능. 75
  76. 76. Global Table의 수평 확장 • HASH(Key) % N 으로 샤드 번호를 구하고 있다. • 부하가 몰릴 때 샤드를 추가하기 쉽지 않다. • Document와 유사한 구조로 수정할 예정. 76
  77. 77. 데드락 방지 어떤 락 A를 잡은 상태에서 락 B를 추가로 잡을 수 있는지를 .schema 파일에 적는다. 규칙에 모순이 없는지 .schema 컴파일 단계에서 확인한다. 락을 잡을 때 규칙을 어겼는지 엔진이 확인해서 예외를 던진다. 77
  78. 78. 변경 로그 자동 작성 모든 데이터 변경 시점마다 변경 로그가 자동으로 남는다. 이것을 되감아서 임의 시점의 유저 DB 상태를 재현할 수 있다. 78
  79. 79. 클라이언트에 Document 변화를 동기화하기 Document 내용을 변경할 때마다 변경사항이 자동 요약됨. 직렬화할 수 있는 형태라서 클라이언트에 전달하기 쉽다. 유저 데이터의 최신 읽기 전용 사본을 클라에 유지할 수 있다. 79
  80. 80. Global Table과 실시간 랭킹 글로벌 테이블에 랭킹을 매기도록 설정할 수 있다. 데이터 쓸 때 Redis의 복제본이 자동으로 갱신된다. 랭킹 관련 조회는 Redis로부터. 불일치가 생기면 점진적으로 데이터 복원 가능. 80
  81. 81. 데이터 저장: 목차 • 주 저장소 • 보조 저장소 81
  82. 82. 보조 저장소 주 저장소로 처리하기 어려운 특이한 요구사항이 가끔 있다. 이런 경우 Redis를 사용해서 만들었다. 82
  83. 83. Cache 만든 값이 일정 시간이 지나면 사라져야 한다. 캐시 용도나 세션 저장 용도로 사용한다. EXPIRE로 구현. 83
  84. 84. Ephemeral 값을 생성한 프로세스가 죽으면 값이 자동으로 지워져야 한다. Apache ZooKeeper™의 ephemeral node를 모방함. 세션 키 저장에 사용한다. GET_LOCK으로 프로세스 죽음을 감지하고, 죽은 프로세스가 만든 값들을 다른 프로세스가 지워주게 구현. 84
  85. 85. TimeSeriesData 시간이 흐름에 따라 변하는 데이터를 요약해서 저장해야 한다. 성능 프로파일러와 실시간 라이브 지표 요약기에서 사용한다. 미리 정한 시간 간격마다, 사건이 발생한 횟수, 데이터의 최소값/최대값/총합으로 요약한다. 원본 데이터 분량이 매우 많을 수 있다. 프로세스에서 먼저 한 번 요약한다. Redis에 저장하면서 추가 요약한다. 85
  86. 86. 보조 저장소의 수평 확장 • (HASH(Key) % N) 해서 샤드 번호를 구한다. 86
  87. 87. Redis 데이터 저장 옵션을 켜는가? 처음에는 켰지만, 끄는 쪽으로 엔진 수정 중. 일부 기능은 MySQL로 옮기거나 합치고 일부 기능은 제거 • 이유 1: 저장 옵션에 의한 Redis 성능 저하 자세한 설명은 생략 • 이유 2: 유연한 하드웨어 사용 HASH(Key) % N 으로 샤딩하기 때문에, Redis 인스턴스를 추가하거나 줄이기 매우 어렵다. 따라서 부하를 정확히 예측해야 하는데, 쉽지 않은 일이다. 데이터를 아예 저장 안하기로 결정하면, 오픈 시점에 Redis를 많이 투입해 두었다가 점검 때 줄이면 됨. 점검 후에 데이터가 사라져도 괜찮다면 인스턴스 개수를 바꾸는 일이 대단히 쉬워진다. 87
  88. 88. Redis와 MySQL을 통합하는 방법 • MySQL이 원본이고 Redis가 사본인 경우 Global Table의 실시간 랭킹 처리. MySQL→Redis로 재동기화하는 절차를 언제 쓸 지 모르니 미리 만들어둬야 한다. • Redis에서 요약하고 가끔씩 MySQL로 옮기는 경우 TimeSeriesData. 장애가 생기면 일부 데이터는 손실될 수 있다. • Redis에만 값이 있고 날아가면 사라지는 경우 Cache와 Ephemeral. 원래 그런 성격의 데이터이니까 괜찮다. 별다른 조치가 필요 없다. 88
  89. 89. 감사합니다 모바일인프라실 데이터베이스 설계에 여러모로 도움을 얻었습니다 89
  90. 90. 설계: 네트워킹 90
  91. 91. 네트워킹: 목차 • 클라이언트와 통신 – 지원하는 프로토콜 – 세션 관리 – 재접속 처리 • 서버끼리 통신 – 서버를 상대로 메시지 전달 – 세션 핸들러를 상대로 메시지 전달 – VActor 91
  92. 92. 클라이언트와 통신: 지원하는 프로토콜 TCP 자체 프로토콜 boost::asio로 구현 HTTP와 WebSocket uWebSockets로 구현 UDP는 아직 92
  93. 93. 요청 처리하기 TCP, WebSocket : 1 세션 = 1 파이버 같은 세션에서 연속 발생하는 요청은 동시 실행되지 않게 HTTP : 1 요청 = 1 파이버 도착하는 요청마다 일단 파이버 스폰부터 93
  94. 94. 재접속 처리 Wifi에서 LTE로 옮겨타도 스트림이 유지되어야 한다 스트림이 유지된다 = 손실되는 메시지가 없다 애플리케이션 레벨에서 아직 수신 확인 받지 않은 메시지를 보관 연결이 복구되면 재전송 94
  95. 95. 재접속 처리: 로드밸런싱 AWS Elastic Load Balancer를 쓰려니… 끊겨서 재접속하니까 아까 연결했던 그 서버가 아니네?;; 재접속할 때는 서버 고유의 public IP를 쓰도록 급히 수정 95
  96. 96. 재접속 처리: 무점검 패치 서버를 업데이트하면서 유저가 느끼지 못하게 하려면? 세션 핸드오버 클라이언트가 로직 코드 모르게 다른 서버로 이동할 수 있게 하기 로직 데이터와 아직 수신 확인 받지 못한 메시지를 Redis에 저장 클라이언트가 다른 서버로 연결하면 Redis에서 데이터를 꺼내와서 스트림을 복구 같은 서버로 연결해야만 하는 경우 (MMORPG) 세션 핸드오버를 사용할 수 없음 96
  97. 97. 네트워킹: 목차 • 클라이언트와 통신 – 지원하는 프로토콜 – 세션 관리 – 재접속 처리 • 서버끼리 통신 – 서버를 상대로 메시지 전달 – 세션 핸들러를 상대로 메시지 전달 – VActor 97
  98. 98. 서버를 상대로 메시지 전달 서버 프로세스의 UPID를 지정해서 메시지를 발송할 수 있다 UPID = Unique Process ID. 프로세스 시작할 때 자동 발급되는 고유번호 현재는 메시지가 Redis를 경유하게 구현함 이걸 게임 로직에서 그대로 활용하기에는 좋지 않다 어느 서버가 떠 있는지 + 어떤 역할을 하는지 알 방법이 필요 다른 서버간 통신의 기초 부품으로 활용하고 있음 98
  99. 99. 세션 핸들러를 상대로 메시지 전달 1 다른 유저에게 메시지를 보내려면? 목적지 = <상대 유저가 접속한 프로세스의 UPID, SessionID> 둘 다 모른다! 99
  100. 100. 세션 핸들러를 상대로 메시지 전달 2 어느 프로세스에 접속했는지 모르는 유저에게 메시지를 보내려면? 세션 핸들러를 초기화할 때 고유 식별자(세션 키)를 등록하게 함 세션 핸들러 = 클라이언트가 서버에 접속하면 서버에 생기는 객체 세션 키로는 유저 id를 사용할 것을 권장 세션 키를 대상으로 메시지를 발송하면 된다 엔진이 세션 키로부터 <UPID, SessionId> 를 자동으로 알아내서 보내준다 100
  101. 101. VActor 1 다른 서버 프로세스에 있는 기능을 호출하려면? 예) 길드 채팅, 파티 멤버 관리, 턴제 게임 PVP 어느 서버가 어떤 기능을 처리할 수 있는지 알아내고 메시지를 보내고 응답을 기다려야 한다 절차 전체를 하나로 묶음. MS Research의 Project Orleans를 크게 참고함. 101
  102. 102. VActor 2 서버 프로세스가 부팅하는 시점에, 자신이 어떤 기능을 처리할 수 있는지(VActor 타입)를 등록한다. 호출 측에서는 VActor의 타입과 이름을 상대로 요청을 보낸다. 처음으로 호출이 일어날 때 서버 어딘가에 VActor가 생겨난다. 102
  103. 103. VActor 3 VActor에는 명시적인 생성/파괴가 없다. 존재한다고 치고 그냥 사용하면 됨 한동안 쓰이지 않으면 사라진다 (스왑아웃) 자신의 데이터를 Redis나 DB에 저장할 수 있다 다음 호출이 일어날 때 활성화된다 (스왑인) 저장했던 데이터를 가지고 원래 상태로 복구할 수 있다 103
  104. 104. VActor 4 장점: 자연스러운 스케일아웃 해당 기능을 어느 서버 프로세스에서 제공하는지는 호출자의 관심사가 아니다. 생성/파괴도 자동이다. 장점: 무점검 패치 가능! 서버가 종료하면서 모든 VActor를 스왑아웃한다. 그 VActor들에 호출이 일어나면 다른 게임서버 프로세스로 스왑인된다. 104
  105. 105. 설계: 백오피스 105
  106. 106. 백오피스란 • 서비스에 꼭 필요한 기능을 백오피스로 분류했다. • 상대적으로 개발 진도가 가장 뒤떨어져 있음. 106
  107. 107. 에러리포트 • 서버에서 발생하는 오류를 수집하고 보고할 수 있어야 한다. • C#이므로 스택 트레이스를 보내는 정도로 해두었음. • 아직 C++ 부분의 오류를 분석해야 하는 상황은 만나지 못함. 107
  108. 108. 디플로이먼트 1 서버 프로그램을 서버 장비에 배포하고 작동시켜야 한다. 특히 오토스케일링 될 때. 서버 환경을 간단하게 생성할 방법이 필요하다. 개발/테스트용 서버 구축하는 일이 꽤 귀찮고, 은근히 많다. 108
  109. 109. 디플로이먼트 2 Docker, Kubernetes, …? 장비(클라우드 인스턴스)는 모바일인프라실에서 다 해주심! 게임서버를 자동 업데이트하고 장비 종류별로 실행 개발/테스트 서버는 모든 게임이 하나의 장비를 공유해서 씀 109
  110. 110. 성능 프로파일링 느릴 때 왜 느린지 알 수 있어야 한다. CPU, 메모리 지표로는 부족하다. 어디에서 시간을 잡아먹는지 어떤 기능을 빈번하게 호출하는지 바로 알 수 있어야 한다. 110
  111. 111. 모니터링 주요 지표를 기록하고, 문제가 있으면 알람을 띄워야 한다. 성능 지표도 CPU나 메모리 사용량만으로는 부족하다. 초당 요청 처리량 세션 개수 연결되어 있는 소켓 개수 등록되어 있는 타이머 개수 DB 조회 횟수 활성화된 VActor 개수 메인 스레드 점유율, 지연 시간 백그라운드 스레드 지연 시간 파이버별 실제 CPU 사용 시간 111
  112. 112. 분석/배치 작업 질문에 대한 대답을 데이터로부터 얻어낼 수 있어야 한다. 대량의 데이터를 일괄 변경할 수 있어야 한다. 어뷰저 찾아내기, 부정 획득 재화 회수하기 등에 필요. 데이터가 메타데이터 없는 json으로 저장되어 있으므로 DB 쿼리를 사용하기는 어렵다. NDC 2015 <쿠키런 로그 시스템> 을 참고하려고 함. 112
  113. 113. 운영툴 게임 내의 데이터를 조회하거나 서버를 원격제어할 수 있는 도구가 필요하다. 웹으로 운영툴 기반을 만들었다. JQuery + 자체 제작 웹 프론트엔드 프레임워크(Jul8) 를 사용한다. 너무 빨리 바뀌는 웹 트렌드 일일이 따라잡지 않아도 되도록. 이와 별개로 사내 표준 운영툴 GUI도 사용한다. 운영 조직이 사용하실 도구를 만드는 데 쓴다. 113
  114. 114. 목차 • 시작 • 목표 • 선택 게임 로직 작성하는 언어 / 데이터베이스 • 설계 동시성 처리 / 데이터 저장 / 네트워킹 / 백오피스 • 의미 114
  115. 115. 의미 115
  116. 116. 이 발표의 의미? 스크린샷: 카카오내비 116
  117. 117. 시작 117
  118. 118. 목표 엔진을 사용하는 게임이 성공한다 많은 프로젝트 / 적은 리스크 / 적은 비용 / 유니크함 낮은 진입장벽 적은 제약 유저 데이터 보호 규모가변성 내결함성 풍부한 기능 사용하기 쉽게 잘못 사용하기 어렵게 지금은 곤란합니다 잠시만 >_< 118
  119. 119. 스튜디오 공용 엔진을 만든다는 것의 의미? 노하우를 축적하고 전파하는 것 이렇게 하는 게 최선이라는 베테랑들의 권고가 엔진 설계에 녹아있다. 119
  120. 120. 노하우를 전파하는 다른 방법? 말이나 글로 표현한다? 정보가 엄청나게 손실된다. 다시 코드로 만들려면 상당한 시간이 걸린다. 프로젝트 코드를 통째로 가져간다? 재사용할 수 있는 것과 없는 것, 잘했던 것과 잘못했던 것을 구분하기 어렵다. 120
  121. 121. 왜 최신 기술을 쓰지 않나요? 여기가 최전선이고, 저희가 만드는 것이 최신 기술입니다. 121 https://github.com/devcat-studio/SilvervineServerEngine2-Doc
  122. 122. WE ARE HIRING 최전선에서 함께, 미래를 만들어갈 분을 찾습니다. 데브캣 스튜디오 서버엔진팀 프로젝트 MV 서버 프로그래머 채용 공고 https://devcat-studio.github.io/recruit/mv_server 122

×