SlideShare uma empresa Scribd logo
1 de 78
Baixar para ler offline
Akka.NET 으로 만드는 온라인 게임 서버
김이선
veblush@gmail | github/veblush
목차
1. 도입
2. 왜 Akka.NET ?
3. Akka.NET 소개
4. Akka.NET 에 더해 만들 것들
5. 틱택토 대전으로 살펴보는 사용 예
6. 결론
과거 프로젝트의 서버?
카트라이더 (2004) 에버플래닛 (2010) 돌격전차 (2015)
P2P 온라인 게임 서버
C++ / IOCP Socket
온라인 MMORPG 서버
C++ / IOCP Socket
모바일 온라인 게임 서버
C# / IOCP Socket
소규모 팀
- 서버 개발팀이 따로 없음. 모두가 전부를 커버하는 구조.
- 클라이언트 중심으로 개발하다가 적당한 시점에 서버를 만들어 붙임.
- 카트라이더의 경우 3차 클베 직전에 서버 작성. (단일 서버)
개발 과정
빠른 개발의 명암
- 2~4주 안에 만들다 보면 요구 조건만 빠듯하게 만족하는 구조가 됨
- 기민하고 낭비 없는 개발이지만…
- 업데이트 컨텐츠를 개발하는 과정에서 한계가 일찍 드러남.
- 서버 구조를 라이브 시점에 크게 바꾸기는 어렵다
개발 과정
좀 더 시간을 써서 유연한 틀을 개발/확보해보자
- 총 3개월!
- 리서치 + 테스트 게임 만들기
- 적당한 수준까지만
- 리서치: Akka.NET, Orleans,…
- 레퍼런스 앱 제작: Chatty, TicTacToe, Snake
Akka.Net + α 로 결정
- 왜?
리서치
왜 Akka.NET ?
뭐지?
액터 모델을 제공하는 Java/Scala 툴킷
Akka 의 .NET 포팅 라이브러리.
Akka.NET ?
온라인 게임은 보통 Stateful
- 유저 상태, 월드 상태, …
- 실시간으로 유저 상호작용 발생
액터 모델은 많은 수의 Stateful 개체를 다루기 좋음
- 때문에 많은 온라인 게임에서 사용하고 있음
왜 액터 모델?
State
Behaviour
M1M2M3
Actor
// actor.receiver
UserActor.OnChat(Chat m) {
_count += 1;
Print(m.Message);
}
// sender
GetUserActor().Send(
new Chat { Message = "Hello?" });
왜 액터 모델?
_count
OnChat
M1M2M3
UserActor
클라이언트와 언어/환경을 맞추기 위해
- 클라이언트는 Unity3D
- 클라이언트/서버 로직 코드 공유 가능
- 양쪽 모두를 작업할 때 컨텍스트 전환 비용 적음
괜찮은 플랫폼
- 적당한 성능 :)
- .NET Core 를 지원하면 서비스 플랫폼 선택의 폭이 넓어짐!
왜 .NET?
선택 때 염두 한 것
- 활동 중인 오픈 소스
- 바로 사용할 수 있을 정도로 성숙한 상태
- .NET 3.5 지원이 어렵지 않을 것 (Unity3D)
후보
- 내부 라이브러리
- Orleans http://dotnet.github.io/orleans
- Akka.NET http://getakka.net
왜 Akka.NET ?
내부에 있는걸 개선하는 방향
- 직전 프로젝트 “돌격전차” 때 싸게 만든 라이브러리를 발전시키는 방향
- 특정 게임에 특화된 라이브러리를 범용화 하는 것은 많은 작업 필요
빠른 포기
- 작은 팀이 (게임도 하면서만들면서 하기엔) 할 일이 많다고 판단
- 재미있겠지만…
후보: 내부 라이브러리
MS 리서치의 오픈 소스 프로젝트
- 몇 년의 연구 끝에 2015년에 1.0 발표
- 여러 클라우드에서 동작 가능
- Azure Service Fabric 과는 다르다
Virtual Actor
- 기존 라이브러리와 다르게 Virtual Actor 개념 도입
- 메모리의 GC 처럼 개발을 쉽게 하기 위한 개념
- 좋아 보이지만…
후보: Orleans
Akka 의 .NET 포팅 라이브러리
- Akka 는 2011년에 1.0 이 나왔으며 여러 곳에서 사용되며 검증됨
- Akka.NET 은 2015년에 1.0 이 나왔음
모듈구조
- 필요한 기능의 모듈만 쓸 수 있다 (Remote, Cluster 도 모듈)
- 모듈을 교체해서 사용할 수 있다 (Serializer 등)
후보: Akka.NET
강점
- 모듈 구조라 상황에 맞춰 커스터마이징을 쉽게 할 수 있다.
- 오픈 소스라 구조 파악 / 버그 수정이 가능하다.
- 클래식 모델이지만 검증된 모델이다.
약점
- 1.0 이 나온 지 얼마 되지 않아 여러 이슈에 시달릴 수 있다
- Remote 성능 개선 작업이 아직 진행 중이다
- 다만 API 는 Akka 의 것이라 안정적이다
선정: Akka.NET
Akka.NET 소개
기본적인 내용만 간략히
Actor
- 상태를 가짐
- 메시지를 받음
- 한 번에 하나의 메시지를 처리함
State
Behaviour
M1M2M3
Actor
Actor
class HelloActor : ReceiveActor {
int _count;
public HelloActor() {
Receive<Hello>(m => {
_count += 1;
Console.WriteLine($"Hello {m.Who}")});
}
_count
OnHello
M1M2M3
HelloActor
ActorRef
- 액터는 ActorRef 라는 핸들로만 접근
- ActorRef 를 통해 액터에 메시지 전송
- 원격에 있는 액터에도 보낼 수 있음
State
Behaviour
M1M2M3
Actor
ActorRef
ActorRef
// create actor
IActorRef greeter =
system.ActorOf<HelloActor>("greeter");
// send message
greeter.Tell(new Hello("World"));
_count
OnHello
M1M2M3
greeter
greeterHello(“World”)
Actor 계층 구조
- 액터가 새 액터를 생성할 때 자식으로 만들 수 있음
- 자식 액터가 예외를 던지면 부모가 처리 할 수 있음
Actor
Actor
Actor Actor
Exception
Resume|Restart|
Stop|Escalate
Actor 계층 구조
class Worker : UntypedActor {
IActorRef counterService =
Context.ActorOf<CounterService>("counter");
override SupervisorStrategy SupervisorStrategy() {
return new OneForOneStrategy(ex => {
if (ex is ServiceUnavailableException)
return Directive.Stop;
return Directive.Escalate;
});
}
원격
원격 Actor 에 메시지를 보낼 수 있음
- ActorRef 에 대상 주소 정보
- 위치 투명성
원격 Actor 를 만들 수 있음
State
Behaviour
M1M2M3
Actor
ActorRef
NodeA
NodeB
NodeA:Actor
원격
// 서버
using (var system = ActorSystem.Create("MyServer", config)) {
system.ActorOf<HelloActor>("greeter");
...
}
// 클라이언트
using (var system = ActorSystem.Create("MyClient", config)) {
IActorRef greeter = system.ActorSelection(
"akka.tcp://MyServer@localhost:8080/user/greeter");
greeter.Tell(new Hello("World"));
}
클러스터
Remote 를 확장해 클러스터 구현
멤버쉽 관리
- Gossip 프로토콜 사용 (SPOF/B 없음)
- 노드 Role 지정
클러스터 유틸리티 제공
- Singleton, Sharding, 분산 Pub/Sub 등
NodeA
NodeB
NodeC
클러스터
class SimpleCluster : UntypedActor {
Cluster Cluster = Cluster.Get(System);
override void OnReceive(object message) {
var up = message as ClusterEvent.MemberUp;
if (up != null) {
Print("Up: {0}", up.Member);
}
}
NodeC
NodeB
A
NodeA
B
C
C
A B
Akka.NET 에 더해 만들 것들
이것만으로 온라인 게임을 만들기엔 부족하지…
Actor
NodeA NodeB
Client
Interface
DB?
State Sync
Discovery / Table
Akka.Interfaced
https://github.com/SaladLab/Akka.Interfaced
Actor
NodeA NodeB
Interface
Akka.Interfaced
코드를 좀 더 간결하게 작성할 수 있도록
- 메시지 클래스 불필요
- 메시지 처리는 인터페이스 메소드 구현으로
- Orleans, WCF 에 영향 받음
액터 구현과 사용에 있어 타입 오류가 없도록
- 인터페이스 상속으로 구현 여부를 컴파일 시점에 확인
- 인터페이스 호출로 메시지가 올바른지 컴파일 시점에 확인
IHello
Akka.Interfaced
IHello
_count
OnHello
M1M2M3
greeter
greeterHello(…)
_count
IHello
.Hello
M1M2M3
greeter
greeterIHello.Hello(…)
Akka.NET 스타일
// define message
class Hello { public string Name; }
class HelloResult { public string Say; }
// implement actor
class HelloActor : ReceiveActor {
public HelloActor() {
Receive<Hello>(m => {
Sender.Tell(new HelloResult($"Hello {m.Name}!")});
});
// use actor
var result = await actorRef.Ask<HelloResult>(new Hello("World"));
Print(result.Say);
Akka.Interfaced 스타일
// define interface
interface IHello : IInterfacedActor {
Task<string> SayHello(string name);
}
// implement actor
class HelloActor : InterfacedActor<HelloActor>, IHello {
async Task<string> IHello.SayHello(string name) {
return $"Hello {name}!";
}
// use actor
Print(await helloRef.SayHello("World"));
Akka.Interfaced.SlimSocket
https://github.com/SaladLab/Akka.Interfaced.SlimSocket
Actor
NodeA NodeB
Client
Interface
Akka.Interfaced.SlimSocket
Akka 에는 클라이언트 역할이라는 개념이 없다
- 기본적으로 모든 액터에게 메시지를 보낼 수 있음
SlimSocket 은 이를 제한함
- 클라이언트는 허용된 액터에게 허용된 인터페이스만 사용 가능
이 시점에서 .NET 3.5 지원
- Actor 에게 메시지만 보내는 기능만 필요하므로 구현할 것이 적음
- Actor 생성, 계층구조, 클러스터, ... 다 필요 없음
Akka.Interfaced.SlimSocket
Actor1Ref
Client Server
SlimSocket.Client SlimSocket.Server
Actor1 Actor2
ClientSession
Actor2Ref
protobuf/tcp
Akka.Cluster.Utility
https://github.com/SaladLab/Akka.Cluster.Utility
Actor
NodeA NodeB
?
Discovery / Table
Akka.Cluster.Utility: ActorDiscovery
Actor Discovery
- 관심 있는 Actor 를 찾아내기 위해
Akka.Cluster.Utility: ActorDiscovery
NodeA NodeB
ActorDiscovery ActorDiscovery
UserActor ServiceActor UserActor UserActor
Register
Notify Notify
share state
Listen Listen
Akka.Cluster.Utility: ActorDiscovery
// register actor
class ServiceActor {
override void PreStart(){
Discovery.Tell(new Register(Self, nameof(ServiceActor)));
}
// discover registered actor
class UserActor {
override void PreStart() {
Discovery.Tell(new Monitor(nameof(ServiceActor)));
}
void OnActorUp(ActorUp m) { ... }
void OnActorDown(ActorDown m) { ... }
Akka.Cluster.Utility: DistributedActorTable
Distributed Actor Table
- 여러 클러스터 노드에 분산되는 액터 테이블
- Sharding 과 유사하나 좀 더 단순한 구현체
- 마스터 테이블 존재 (SPOF/B)
Akka.Cluster.Utility: DistributedActorTable
NodeA NodeB
ActorTable
ID ActorRef
1 Actor1
2 Actor2
3 Actor3
NodeC
Actor1
Actor2
Actor3
Actor4
Akka.Cluster.Utility: DistributedActorTable
// create table
var table = System.ActorOf(
Props.Create(() => new Table("Test", ...)));
// create actor on table
var reply = await table.Ask<CreateReply>(new Create(id, ...));
reply.Actor;
// get actor from table
var reply = await table.Ask<GetReply>(new Get(id));
reply.Actor;
TrackableData
https://github.com/SaladLab/TrackableData
Actor
NodeA NodeB
Client DB
State Sync
TrackableData
서버와 클라이언트 상태를 동기화 하기 위해 사용
- 데이터의 상태 변경을 클라이언트 혹은 다른 서버, DB 에 전파
- ORM 보다는 Change Tracking 라이브러리
- .NET 3.5 / Unity3D 지원
- 지원
- Json, Protobuf
- MSSQL, MySQL, postgreSQL, MongoDB, Redis
프로덕션 수준 안정화
- Monster Sweeperz 에 사용
TrackableData
ServerClient DB
User
Gold=10
Cash=20
User
Gold=10
Cash=20
User
Gold=10
Cash=20
User
Gold=15
Cash=20
User
Gold=15
Cash=20
User
Gold=15
Cash=20
CreateSnapshot
Gold+=5Change Save
TrackableData
interface IUserData : ITrackablePoco<IUserData> {
string Name { get; set; }
int Level { get; set; }
int Gold { get; set; }
}
var u = new TrackableUserData();
// make changes
u.Name = "Bob";
u.Level = 1;
u.Gold = 10;
Print(u.Tracker);
// { Name:->Bob, Level:0->1, Gold:0->10 }
틱택토 대전으로 살펴보는 사용 예
라이브러리가 잘 동작하는지 확인 하기 위한 레퍼런스 게임
기능
유저 계정
- 유저 ID, 패스워드로 로그인
- 유저의 전적과 업적이 DB에 저장됨
유저간 실시간 대전
- 턴제 (턴 타임아웃 있음)
- 대전 상대를 매치메이킹 서버를 통해 찾음
- 못찾으면 봇이 대신 참여
https://github.com/SaladLab/TicTacToe
프로젝트 구성
Domain
Domain.Tests
GameServer
GameServer.Tests
GameClient
450 cloc
965 cloc
1141 cloc
GameUser
Game
GameBot
User
클러스터 노드 구성
User
User
Login
Game
GamePair
Maker
GameBot
User
Table
Game
Table
Master User Game
액터 구성
Client
Client
Session User
User
Login
Game
GamePair
Maker
GameBot
MongoDB
주요 동작
로그인 매치메이킹 게임 입장 게임 진행 게임 종료
로그인
로그인 액터를 통해 계정 인증을 하고 유저 액터를 받는다
- 로그인 액터는 클라이언트가 접속하면 가장 처음 받는 액터
클라이언트는 허용된 액터와 인터페이스로만 서버와 통신 가능
- 허용된 액터라도 허용받지 않은 인터페이스로 통신할 수 없다.
로그인: 액터
Client
Client
Session User
User
Login MongoDB
Login
Create
Bind
로그인: 코드
// client requests login to server
var t1 = login.Login(id, password, observerId);
yield return t1.WaitHandle;
// check account, create user actor and bind it to client
async Task<LoginResult> IUserLogin.Login(id, password) {
var userId = CheckAccount(id, password);
var user = CreateUserActor(userId);
await UserTable.AddUserAsync(userId, user);
var bindId = await ClientSession.BindAsync(user, typeof(IUser));
// client gets user actor
var user = new UserRef(t1.Result);
매치메이킹
동작
- 클라이언트는 매칭 요청을 서버에 보내고 일정 시간 기다림.
- 매칭 서버는 요청을 큐에 쌓으며 2명이 되면 짝을 지어줌.
- 타임아웃이 되면 봇 액터와 짝을 지어줌
매치메이킹: 액터
Client
Client
Session User
Game
GamePair
Maker
Register
Create
Created
매치메이킹: 코드
// client requests pairing from UserActor
yield return G.User.RegisterPairing(observerId).WaitHandle;
// UserActor forwards a request to GamePairMakerActor
class GamePairMakerActor : ... {
void RegisterPairing(userId, userName, ...) {
AddToQueue(userId);
}
void OnSchedule() {
if (Queue.Count >= 2) {
user0, user1 = Queue.Pop(2);
CreateNewGame();
user0.SendNoticeToUser(gameId);
user1.SendNoticeToUser(gameId);
게임 입장
동작
- 서버는 매 게임마다 새 GameRoom 액터 생성
- 유저는 매치 메이킹 결과로 입장할 GameRoom ActorRef 받음
- 유저는 GameRoom 에 입장하면서 GameObserver 를 등록
- GameObserver 를 통해 유저는 게임 이벤트를 받음
게임 입장: 액터
Client
Client
Session User
Game
Join
Join
Bind
게임 입장: 코드
// client sends a join request to UserActor.
var ret = G.User.JoinGame(roomId, observerId);
yield return ret.WaitHandle;
// UserActor forwards a request to GameActor.
// when done, grant GameActor to Client as IGamePlayer.
class UserActor : ... {
async Task<...> IUser.JoinGame(long gameId, int observerId) {
var game = await GameTable.GetAsync(gameId);
await game.Join(...);
var bindId = await BindAsync(game.Actor, typeof(IGamePlayer));
return ...;
}
게임 진행
동작
- 클라이언트는 입장 때 받은 GamePlayer 액터로 게임 진행
- 게임 이벤트 (상대의 턴, 게임 승패 이벤트 등) 은
GameObserver 로 처리
게임 진행: 턴 명령: 액터
Client
Client
Session
Game
MakeMove
GameRef.MakeMove(2,1)
게임 진행: 턴 명령: 코드
// client sends a move command to GameActor
class GameScene : MonoBehaviour, IGameObserver {
void OnBoardGridClicked(int x, int y) {
_myPlayer.MakeMove(new PlacePosition(x, y));
}
// GameActor proceeds the game by command
public class GameActor : ... {
void MakeMove(PlacePosition pos, long playerUserId) {
DoGameLogic();
...
}
게임 진행: 진행 이벤트: 액터
Game
Client
Session
MakeMove
Client
GameObserver.MakeMove(2,1)
MakeMove
게임 진행: 진행 이벤트: 코드
// GameActor broadcasts game events to clients
public class GameActor : ... {
void MakeMove(PlacePosition pos, long playerUserId) {
...
NotifyToAllObservers((id, o) => o.MakeMove(...));
}
// client consumes game events
class GameScene : MonoBehaviour, IGameObserver {
void IGameObserver.MakeMove(...) {
Board.SetMark(...);
}
게임 종료
동작
- 게임 액터 소멸
- 유저 액터에게 게임 종료를 알리고 유저 상태 업데이트
- 상태 변경을 TrackableData 로 클라이언트와 DB 에 전파
게임 종료: 액터
Client
Client
Session User
Game
End
End
MongoDB
Update
Update
Kill
게임 종료: 코드
// UpdateActor updates user state when the game is over
void IGameUserObserver.End(long gameId, GameResult result) {
_userContext.Data.GameCount += 1;
// flush changes to client and storage
_userEventObserver.UserContextChange(_userContext.Tracker);
MongoDbMapper.SaveAsync(_userContext.Tracker, _id);
_userContext.Tracker = new TrackableUserContextTracker();
}
// when no one left in GameActor, kill actor
void Leave(long userId) {
NotifyToAllObservers((id, o) => o.Leave(playerId));
if (_players.Count() == 0) {
Self.Tell(InterfacedPoisonPill.Instance);
결론
Akka.NET
쓸만하다!
- Akka.NET 은 쓸만한 빌딩 블록.
- 부분적으로 필요한 곳에서만 쓸 수 있다.
- Akka.Interfaced 등을 통해 Unity3D 에서도 손쉽게 사용 가능.
라이브러리는 아직 초기 상태임을 염두
- 거의 대부분 잘 돌아간다.
- “성숙했다” 라고 하기엔 아직 시간이 필요.
- 문제 발생 때 늘 의심해야 하는 단계 
시도해 보기
TicTacToe
- 소스를 받아 실행해 보기: https://github.com/SaladLab/TicTacToe
라이브러리 써보기
- 프로젝트 Github 방문
- Nuget / Github Release 에서 라이브러리 받기
오픈소스
모든 것이 오픈 소스!
- 사용하고 작성한 모든 것이 오픈 소스
- 기대
- 품질이 보다 더 좋아지지 않을까?
- 개발된 라이브러리가 게임과 같이 소멸하지는 않겠지?
참여해보자!
- 버그 리포트, 기능 제안
- 더 나아가서 내부 라이브러리, 툴을 오픈 소스로 만들어 보자!
감사합니다.

Mais conteúdo relacionado

Mais procurados

Multiplayer Game Sync Techniques through CAP theorem
Multiplayer Game Sync Techniques through CAP theoremMultiplayer Game Sync Techniques through CAP theorem
Multiplayer Game Sync Techniques through CAP theoremSeungmo Koo
 
임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013devCAT Studio, NEXON
 
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games ConferenceKGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games ConferenceXionglong Jin
 
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버Heungsub Lee
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직Hoyoung Choi
 
게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가Seungmo Koo
 
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지강 민우
 
쿠키런 1년, 서버개발 분투기
쿠키런 1년, 서버개발 분투기쿠키런 1년, 서버개발 분투기
쿠키런 1년, 서버개발 분투기Brian Hong
 
송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010devCAT Studio, NEXON
 
MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현YEONG-CHEON YOU
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조Hyunjik Bae
 
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버준철 박
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019devCAT Studio, NEXON
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)Heungsub Lee
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템QooJuice
 
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)Seungmo Koo
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018devCAT Studio, NEXON
 
파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)Heungsub Lee
 
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3Heungsub Lee
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델Seungmo Koo
 

Mais procurados (20)

Multiplayer Game Sync Techniques through CAP theorem
Multiplayer Game Sync Techniques through CAP theoremMultiplayer Game Sync Techniques through CAP theorem
Multiplayer Game Sync Techniques through CAP theorem
 
임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013
 
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games ConferenceKGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
KGC 2016: HTTPS 로 모바일 게임 서버 구축한다는 것 - Korea Games Conference
 
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직
 
게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가게임서버프로그래밍 #8 - 성능 평가
게임서버프로그래밍 #8 - 성능 평가
 
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
[IGC 2017] 아마존 구승모 - 게임 엔진으로 서버 제작 및 운영까지
 
쿠키런 1년, 서버개발 분투기
쿠키런 1년, 서버개발 분투기쿠키런 1년, 서버개발 분투기
쿠키런 1년, 서버개발 분투기
 
송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010
 
MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현
 
게임 분산 서버 구조
게임 분산 서버 구조게임 분산 서버 구조
게임 분산 서버 구조
 
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
 
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
사설 서버를 막는 방법들 (프리섭, 더이상은 Naver)
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
 
파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)
 
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
 

Semelhante a Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)

[오픈소스컨설팅] ARM & OpenStack Community
[오픈소스컨설팅] ARM & OpenStack Community[오픈소스컨설팅] ARM & OpenStack Community
[오픈소스컨설팅] ARM & OpenStack CommunityOpen Source Consulting
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기SeungYong Oh
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020Ji-Woong Choi
 
오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기Jaehwa Park
 
SOSCON 2017 - Backend.AI
SOSCON 2017 - Backend.AISOSCON 2017 - Backend.AI
SOSCON 2017 - Backend.AIJoongi Kim
 
AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...
AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...
AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...JooHyung Kim
 
Provisioning Dedicated Game Server on Kubernetes Cluster
Provisioning Dedicated Game Server on Kubernetes ClusterProvisioning Dedicated Game Server on Kubernetes Cluster
Provisioning Dedicated Game Server on Kubernetes ClusterJinwoong Kim
 
[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...
[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...
[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...OpenStack Korea Community
 
성공적인 게임 런칭을 위한 비밀의 레시피 #3
성공적인 게임 런칭을 위한 비밀의 레시피 #3성공적인 게임 런칭을 위한 비밀의 레시피 #3
성공적인 게임 런칭을 위한 비밀의 레시피 #3Amazon Web Services Korea
 
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트Dae Kim
 
Fluentd with MySQL
Fluentd with MySQLFluentd with MySQL
Fluentd with MySQLI Goo Lee
 
Hadoop security DeView 2014
Hadoop security DeView 2014Hadoop security DeView 2014
Hadoop security DeView 2014Gruter
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안Jeongsang Baek
 
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크Jeongkyu Shin
 
오픈 소스 클라우드 플랫폼 분석
오픈 소스 클라우드 플랫폼 분석오픈 소스 클라우드 플랫폼 분석
오픈 소스 클라우드 플랫폼 분석Jennifer Noh
 
Rhea_MMO_SNG_Convergence_Server_Architecture
Rhea_MMO_SNG_Convergence_Server_ArchitectureRhea_MMO_SNG_Convergence_Server_Architecture
Rhea_MMO_SNG_Convergence_Server_ArchitectureRhea Strike
 
[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석
[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석
[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석Tommy Lee
 
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축Ji-Woong Choi
 

Semelhante a Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016) (20)

OpenStack Swift Debugging
OpenStack Swift DebuggingOpenStack Swift Debugging
OpenStack Swift Debugging
 
[오픈소스컨설팅] ARM & OpenStack Community
[오픈소스컨설팅] ARM & OpenStack Community[오픈소스컨설팅] ARM & OpenStack Community
[오픈소스컨설팅] ARM & OpenStack Community
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
 
오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기오픈스택: 구석구석 파헤쳐보기
오픈스택: 구석구석 파헤쳐보기
 
SOSCON 2017 - Backend.AI
SOSCON 2017 - Backend.AISOSCON 2017 - Backend.AI
SOSCON 2017 - Backend.AI
 
AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...
AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...
AWS Community Day 2022 - Nitro Enclave를 이용하여 안전하게 고객 정보 다...
 
Provisioning Dedicated Game Server on Kubernetes Cluster
Provisioning Dedicated Game Server on Kubernetes ClusterProvisioning Dedicated Game Server on Kubernetes Cluster
Provisioning Dedicated Game Server on Kubernetes Cluster
 
[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...
[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...
[OpenInfra Days Korea 2018] (Track 4) Provisioning Dedicated Game Server on K...
 
성공적인 게임 런칭을 위한 비밀의 레시피 #3
성공적인 게임 런칭을 위한 비밀의 레시피 #3성공적인 게임 런칭을 위한 비밀의 레시피 #3
성공적인 게임 런칭을 위한 비밀의 레시피 #3
 
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
 
Kafka slideshare
Kafka   slideshareKafka   slideshare
Kafka slideshare
 
Fluentd with MySQL
Fluentd with MySQLFluentd with MySQL
Fluentd with MySQL
 
Hadoop security DeView 2014
Hadoop security DeView 2014Hadoop security DeView 2014
Hadoop security DeView 2014
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
 
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
 
오픈 소스 클라우드 플랫폼 분석
오픈 소스 클라우드 플랫폼 분석오픈 소스 클라우드 플랫폼 분석
오픈 소스 클라우드 플랫폼 분석
 
Rhea_MMO_SNG_Convergence_Server_Architecture
Rhea_MMO_SNG_Convergence_Server_ArchitectureRhea_MMO_SNG_Convergence_Server_Architecture
Rhea_MMO_SNG_Convergence_Server_Architecture
 
[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석
[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석
[개방형 클라우드 플랫폼 오픈세미나 오픈클라우드 Pub] 3.open shift 분석
 
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
 

Mais de Esun Kim

Online game server on Akka.NET (NDC2016)
Online game server on Akka.NET (NDC2016)Online game server on Akka.NET (NDC2016)
Online game server on Akka.NET (NDC2016)Esun Kim
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013Esun Kim
 
에버플래닛의 글로브뷰 렌더링 NDC2011
에버플래닛의 글로브뷰 렌더링 NDC2011에버플래닛의 글로브뷰 렌더링 NDC2011
에버플래닛의 글로브뷰 렌더링 NDC2011Esun Kim
 
코드 생성을 사용해 개발 속도 높이기 NDC2011
코드 생성을 사용해 개발 속도 높이기 NDC2011코드 생성을 사용해 개발 속도 높이기 NDC2011
코드 생성을 사용해 개발 속도 높이기 NDC2011Esun Kim
 
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012Esun Kim
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012Esun Kim
 

Mais de Esun Kim (6)

Online game server on Akka.NET (NDC2016)
Online game server on Akka.NET (NDC2016)Online game server on Akka.NET (NDC2016)
Online game server on Akka.NET (NDC2016)
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
 
에버플래닛의 글로브뷰 렌더링 NDC2011
에버플래닛의 글로브뷰 렌더링 NDC2011에버플래닛의 글로브뷰 렌더링 NDC2011
에버플래닛의 글로브뷰 렌더링 NDC2011
 
코드 생성을 사용해 개발 속도 높이기 NDC2011
코드 생성을 사용해 개발 속도 높이기 NDC2011코드 생성을 사용해 개발 속도 높이기 NDC2011
코드 생성을 사용해 개발 속도 높이기 NDC2011
 
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
 

Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)

  • 1. Akka.NET 으로 만드는 온라인 게임 서버 김이선 veblush@gmail | github/veblush
  • 2. 목차 1. 도입 2. 왜 Akka.NET ? 3. Akka.NET 소개 4. Akka.NET 에 더해 만들 것들 5. 틱택토 대전으로 살펴보는 사용 예 6. 결론
  • 3. 과거 프로젝트의 서버? 카트라이더 (2004) 에버플래닛 (2010) 돌격전차 (2015) P2P 온라인 게임 서버 C++ / IOCP Socket 온라인 MMORPG 서버 C++ / IOCP Socket 모바일 온라인 게임 서버 C# / IOCP Socket
  • 4. 소규모 팀 - 서버 개발팀이 따로 없음. 모두가 전부를 커버하는 구조. - 클라이언트 중심으로 개발하다가 적당한 시점에 서버를 만들어 붙임. - 카트라이더의 경우 3차 클베 직전에 서버 작성. (단일 서버) 개발 과정
  • 5. 빠른 개발의 명암 - 2~4주 안에 만들다 보면 요구 조건만 빠듯하게 만족하는 구조가 됨 - 기민하고 낭비 없는 개발이지만… - 업데이트 컨텐츠를 개발하는 과정에서 한계가 일찍 드러남. - 서버 구조를 라이브 시점에 크게 바꾸기는 어렵다 개발 과정
  • 6. 좀 더 시간을 써서 유연한 틀을 개발/확보해보자 - 총 3개월! - 리서치 + 테스트 게임 만들기 - 적당한 수준까지만 - 리서치: Akka.NET, Orleans,… - 레퍼런스 앱 제작: Chatty, TicTacToe, Snake Akka.Net + α 로 결정 - 왜? 리서치
  • 8. 액터 모델을 제공하는 Java/Scala 툴킷 Akka 의 .NET 포팅 라이브러리. Akka.NET ?
  • 9. 온라인 게임은 보통 Stateful - 유저 상태, 월드 상태, … - 실시간으로 유저 상호작용 발생 액터 모델은 많은 수의 Stateful 개체를 다루기 좋음 - 때문에 많은 온라인 게임에서 사용하고 있음 왜 액터 모델? State Behaviour M1M2M3 Actor
  • 10. // actor.receiver UserActor.OnChat(Chat m) { _count += 1; Print(m.Message); } // sender GetUserActor().Send( new Chat { Message = "Hello?" }); 왜 액터 모델? _count OnChat M1M2M3 UserActor
  • 11. 클라이언트와 언어/환경을 맞추기 위해 - 클라이언트는 Unity3D - 클라이언트/서버 로직 코드 공유 가능 - 양쪽 모두를 작업할 때 컨텍스트 전환 비용 적음 괜찮은 플랫폼 - 적당한 성능 :) - .NET Core 를 지원하면 서비스 플랫폼 선택의 폭이 넓어짐! 왜 .NET?
  • 12. 선택 때 염두 한 것 - 활동 중인 오픈 소스 - 바로 사용할 수 있을 정도로 성숙한 상태 - .NET 3.5 지원이 어렵지 않을 것 (Unity3D) 후보 - 내부 라이브러리 - Orleans http://dotnet.github.io/orleans - Akka.NET http://getakka.net 왜 Akka.NET ?
  • 13. 내부에 있는걸 개선하는 방향 - 직전 프로젝트 “돌격전차” 때 싸게 만든 라이브러리를 발전시키는 방향 - 특정 게임에 특화된 라이브러리를 범용화 하는 것은 많은 작업 필요 빠른 포기 - 작은 팀이 (게임도 하면서만들면서 하기엔) 할 일이 많다고 판단 - 재미있겠지만… 후보: 내부 라이브러리
  • 14. MS 리서치의 오픈 소스 프로젝트 - 몇 년의 연구 끝에 2015년에 1.0 발표 - 여러 클라우드에서 동작 가능 - Azure Service Fabric 과는 다르다 Virtual Actor - 기존 라이브러리와 다르게 Virtual Actor 개념 도입 - 메모리의 GC 처럼 개발을 쉽게 하기 위한 개념 - 좋아 보이지만… 후보: Orleans
  • 15. Akka 의 .NET 포팅 라이브러리 - Akka 는 2011년에 1.0 이 나왔으며 여러 곳에서 사용되며 검증됨 - Akka.NET 은 2015년에 1.0 이 나왔음 모듈구조 - 필요한 기능의 모듈만 쓸 수 있다 (Remote, Cluster 도 모듈) - 모듈을 교체해서 사용할 수 있다 (Serializer 등) 후보: Akka.NET
  • 16. 강점 - 모듈 구조라 상황에 맞춰 커스터마이징을 쉽게 할 수 있다. - 오픈 소스라 구조 파악 / 버그 수정이 가능하다. - 클래식 모델이지만 검증된 모델이다. 약점 - 1.0 이 나온 지 얼마 되지 않아 여러 이슈에 시달릴 수 있다 - Remote 성능 개선 작업이 아직 진행 중이다 - 다만 API 는 Akka 의 것이라 안정적이다 선정: Akka.NET
  • 18. Actor - 상태를 가짐 - 메시지를 받음 - 한 번에 하나의 메시지를 처리함 State Behaviour M1M2M3 Actor
  • 19. Actor class HelloActor : ReceiveActor { int _count; public HelloActor() { Receive<Hello>(m => { _count += 1; Console.WriteLine($"Hello {m.Who}")}); } _count OnHello M1M2M3 HelloActor
  • 20. ActorRef - 액터는 ActorRef 라는 핸들로만 접근 - ActorRef 를 통해 액터에 메시지 전송 - 원격에 있는 액터에도 보낼 수 있음 State Behaviour M1M2M3 Actor ActorRef
  • 21. ActorRef // create actor IActorRef greeter = system.ActorOf<HelloActor>("greeter"); // send message greeter.Tell(new Hello("World")); _count OnHello M1M2M3 greeter greeterHello(“World”)
  • 22. Actor 계층 구조 - 액터가 새 액터를 생성할 때 자식으로 만들 수 있음 - 자식 액터가 예외를 던지면 부모가 처리 할 수 있음 Actor Actor Actor Actor Exception Resume|Restart| Stop|Escalate
  • 23. Actor 계층 구조 class Worker : UntypedActor { IActorRef counterService = Context.ActorOf<CounterService>("counter"); override SupervisorStrategy SupervisorStrategy() { return new OneForOneStrategy(ex => { if (ex is ServiceUnavailableException) return Directive.Stop; return Directive.Escalate; }); }
  • 24. 원격 원격 Actor 에 메시지를 보낼 수 있음 - ActorRef 에 대상 주소 정보 - 위치 투명성 원격 Actor 를 만들 수 있음 State Behaviour M1M2M3 Actor ActorRef NodeA NodeB NodeA:Actor
  • 25. 원격 // 서버 using (var system = ActorSystem.Create("MyServer", config)) { system.ActorOf<HelloActor>("greeter"); ... } // 클라이언트 using (var system = ActorSystem.Create("MyClient", config)) { IActorRef greeter = system.ActorSelection( "akka.tcp://MyServer@localhost:8080/user/greeter"); greeter.Tell(new Hello("World")); }
  • 26. 클러스터 Remote 를 확장해 클러스터 구현 멤버쉽 관리 - Gossip 프로토콜 사용 (SPOF/B 없음) - 노드 Role 지정 클러스터 유틸리티 제공 - Singleton, Sharding, 분산 Pub/Sub 등 NodeA NodeB NodeC
  • 27. 클러스터 class SimpleCluster : UntypedActor { Cluster Cluster = Cluster.Get(System); override void OnReceive(object message) { var up = message as ClusterEvent.MemberUp; if (up != null) { Print("Up: {0}", up.Member); } } NodeC NodeB A NodeA B C C A B
  • 28. Akka.NET 에 더해 만들 것들 이것만으로 온라인 게임을 만들기엔 부족하지…
  • 31. Akka.Interfaced 코드를 좀 더 간결하게 작성할 수 있도록 - 메시지 클래스 불필요 - 메시지 처리는 인터페이스 메소드 구현으로 - Orleans, WCF 에 영향 받음 액터 구현과 사용에 있어 타입 오류가 없도록 - 인터페이스 상속으로 구현 여부를 컴파일 시점에 확인 - 인터페이스 호출로 메시지가 올바른지 컴파일 시점에 확인
  • 33. Akka.NET 스타일 // define message class Hello { public string Name; } class HelloResult { public string Say; } // implement actor class HelloActor : ReceiveActor { public HelloActor() { Receive<Hello>(m => { Sender.Tell(new HelloResult($"Hello {m.Name}!")}); }); // use actor var result = await actorRef.Ask<HelloResult>(new Hello("World")); Print(result.Say);
  • 34. Akka.Interfaced 스타일 // define interface interface IHello : IInterfacedActor { Task<string> SayHello(string name); } // implement actor class HelloActor : InterfacedActor<HelloActor>, IHello { async Task<string> IHello.SayHello(string name) { return $"Hello {name}!"; } // use actor Print(await helloRef.SayHello("World"));
  • 36. Akka.Interfaced.SlimSocket Akka 에는 클라이언트 역할이라는 개념이 없다 - 기본적으로 모든 액터에게 메시지를 보낼 수 있음 SlimSocket 은 이를 제한함 - 클라이언트는 허용된 액터에게 허용된 인터페이스만 사용 가능 이 시점에서 .NET 3.5 지원 - Actor 에게 메시지만 보내는 기능만 필요하므로 구현할 것이 적음 - Actor 생성, 계층구조, 클러스터, ... 다 필요 없음
  • 39. Akka.Cluster.Utility: ActorDiscovery Actor Discovery - 관심 있는 Actor 를 찾아내기 위해
  • 40. Akka.Cluster.Utility: ActorDiscovery NodeA NodeB ActorDiscovery ActorDiscovery UserActor ServiceActor UserActor UserActor Register Notify Notify share state Listen Listen
  • 41. Akka.Cluster.Utility: ActorDiscovery // register actor class ServiceActor { override void PreStart(){ Discovery.Tell(new Register(Self, nameof(ServiceActor))); } // discover registered actor class UserActor { override void PreStart() { Discovery.Tell(new Monitor(nameof(ServiceActor))); } void OnActorUp(ActorUp m) { ... } void OnActorDown(ActorDown m) { ... }
  • 42. Akka.Cluster.Utility: DistributedActorTable Distributed Actor Table - 여러 클러스터 노드에 분산되는 액터 테이블 - Sharding 과 유사하나 좀 더 단순한 구현체 - 마스터 테이블 존재 (SPOF/B)
  • 43. Akka.Cluster.Utility: DistributedActorTable NodeA NodeB ActorTable ID ActorRef 1 Actor1 2 Actor2 3 Actor3 NodeC Actor1 Actor2 Actor3 Actor4
  • 44. Akka.Cluster.Utility: DistributedActorTable // create table var table = System.ActorOf( Props.Create(() => new Table("Test", ...))); // create actor on table var reply = await table.Ask<CreateReply>(new Create(id, ...)); reply.Actor; // get actor from table var reply = await table.Ask<GetReply>(new Get(id)); reply.Actor;
  • 46. TrackableData 서버와 클라이언트 상태를 동기화 하기 위해 사용 - 데이터의 상태 변경을 클라이언트 혹은 다른 서버, DB 에 전파 - ORM 보다는 Change Tracking 라이브러리 - .NET 3.5 / Unity3D 지원 - 지원 - Json, Protobuf - MSSQL, MySQL, postgreSQL, MongoDB, Redis 프로덕션 수준 안정화 - Monster Sweeperz 에 사용
  • 48. TrackableData interface IUserData : ITrackablePoco<IUserData> { string Name { get; set; } int Level { get; set; } int Gold { get; set; } } var u = new TrackableUserData(); // make changes u.Name = "Bob"; u.Level = 1; u.Gold = 10; Print(u.Tracker); // { Name:->Bob, Level:0->1, Gold:0->10 }
  • 49. 틱택토 대전으로 살펴보는 사용 예 라이브러리가 잘 동작하는지 확인 하기 위한 레퍼런스 게임
  • 50.
  • 51. 기능 유저 계정 - 유저 ID, 패스워드로 로그인 - 유저의 전적과 업적이 DB에 저장됨 유저간 실시간 대전 - 턴제 (턴 타임아웃 있음) - 대전 상대를 매치메이킹 서버를 통해 찾음 - 못찾으면 봇이 대신 참여
  • 56. 주요 동작 로그인 매치메이킹 게임 입장 게임 진행 게임 종료
  • 57. 로그인 로그인 액터를 통해 계정 인증을 하고 유저 액터를 받는다 - 로그인 액터는 클라이언트가 접속하면 가장 처음 받는 액터 클라이언트는 허용된 액터와 인터페이스로만 서버와 통신 가능 - 허용된 액터라도 허용받지 않은 인터페이스로 통신할 수 없다.
  • 59. 로그인: 코드 // client requests login to server var t1 = login.Login(id, password, observerId); yield return t1.WaitHandle; // check account, create user actor and bind it to client async Task<LoginResult> IUserLogin.Login(id, password) { var userId = CheckAccount(id, password); var user = CreateUserActor(userId); await UserTable.AddUserAsync(userId, user); var bindId = await ClientSession.BindAsync(user, typeof(IUser)); // client gets user actor var user = new UserRef(t1.Result);
  • 60. 매치메이킹 동작 - 클라이언트는 매칭 요청을 서버에 보내고 일정 시간 기다림. - 매칭 서버는 요청을 큐에 쌓으며 2명이 되면 짝을 지어줌. - 타임아웃이 되면 봇 액터와 짝을 지어줌
  • 62. 매치메이킹: 코드 // client requests pairing from UserActor yield return G.User.RegisterPairing(observerId).WaitHandle; // UserActor forwards a request to GamePairMakerActor class GamePairMakerActor : ... { void RegisterPairing(userId, userName, ...) { AddToQueue(userId); } void OnSchedule() { if (Queue.Count >= 2) { user0, user1 = Queue.Pop(2); CreateNewGame(); user0.SendNoticeToUser(gameId); user1.SendNoticeToUser(gameId);
  • 63. 게임 입장 동작 - 서버는 매 게임마다 새 GameRoom 액터 생성 - 유저는 매치 메이킹 결과로 입장할 GameRoom ActorRef 받음 - 유저는 GameRoom 에 입장하면서 GameObserver 를 등록 - GameObserver 를 통해 유저는 게임 이벤트를 받음
  • 65. 게임 입장: 코드 // client sends a join request to UserActor. var ret = G.User.JoinGame(roomId, observerId); yield return ret.WaitHandle; // UserActor forwards a request to GameActor. // when done, grant GameActor to Client as IGamePlayer. class UserActor : ... { async Task<...> IUser.JoinGame(long gameId, int observerId) { var game = await GameTable.GetAsync(gameId); await game.Join(...); var bindId = await BindAsync(game.Actor, typeof(IGamePlayer)); return ...; }
  • 66. 게임 진행 동작 - 클라이언트는 입장 때 받은 GamePlayer 액터로 게임 진행 - 게임 이벤트 (상대의 턴, 게임 승패 이벤트 등) 은 GameObserver 로 처리
  • 67. 게임 진행: 턴 명령: 액터 Client Client Session Game MakeMove GameRef.MakeMove(2,1)
  • 68. 게임 진행: 턴 명령: 코드 // client sends a move command to GameActor class GameScene : MonoBehaviour, IGameObserver { void OnBoardGridClicked(int x, int y) { _myPlayer.MakeMove(new PlacePosition(x, y)); } // GameActor proceeds the game by command public class GameActor : ... { void MakeMove(PlacePosition pos, long playerUserId) { DoGameLogic(); ... }
  • 69. 게임 진행: 진행 이벤트: 액터 Game Client Session MakeMove Client GameObserver.MakeMove(2,1) MakeMove
  • 70. 게임 진행: 진행 이벤트: 코드 // GameActor broadcasts game events to clients public class GameActor : ... { void MakeMove(PlacePosition pos, long playerUserId) { ... NotifyToAllObservers((id, o) => o.MakeMove(...)); } // client consumes game events class GameScene : MonoBehaviour, IGameObserver { void IGameObserver.MakeMove(...) { Board.SetMark(...); }
  • 71. 게임 종료 동작 - 게임 액터 소멸 - 유저 액터에게 게임 종료를 알리고 유저 상태 업데이트 - 상태 변경을 TrackableData 로 클라이언트와 DB 에 전파
  • 72. 게임 종료: 액터 Client Client Session User Game End End MongoDB Update Update Kill
  • 73. 게임 종료: 코드 // UpdateActor updates user state when the game is over void IGameUserObserver.End(long gameId, GameResult result) { _userContext.Data.GameCount += 1; // flush changes to client and storage _userEventObserver.UserContextChange(_userContext.Tracker); MongoDbMapper.SaveAsync(_userContext.Tracker, _id); _userContext.Tracker = new TrackableUserContextTracker(); } // when no one left in GameActor, kill actor void Leave(long userId) { NotifyToAllObservers((id, o) => o.Leave(playerId)); if (_players.Count() == 0) { Self.Tell(InterfacedPoisonPill.Instance);
  • 75. Akka.NET 쓸만하다! - Akka.NET 은 쓸만한 빌딩 블록. - 부분적으로 필요한 곳에서만 쓸 수 있다. - Akka.Interfaced 등을 통해 Unity3D 에서도 손쉽게 사용 가능. 라이브러리는 아직 초기 상태임을 염두 - 거의 대부분 잘 돌아간다. - “성숙했다” 라고 하기엔 아직 시간이 필요. - 문제 발생 때 늘 의심해야 하는 단계 
  • 76. 시도해 보기 TicTacToe - 소스를 받아 실행해 보기: https://github.com/SaladLab/TicTacToe 라이브러리 써보기 - 프로젝트 Github 방문 - Nuget / Github Release 에서 라이브러리 받기
  • 77. 오픈소스 모든 것이 오픈 소스! - 사용하고 작성한 모든 것이 오픈 소스 - 기대 - 품질이 보다 더 좋아지지 않을까? - 개발된 라이브러리가 게임과 같이 소멸하지는 않겠지? 참여해보자! - 버그 리포트, 기능 제안 - 더 나아가서 내부 라이브러리, 툴을 오픈 소스로 만들어 보자!