Upload
maciej-mroz
View
1.307
Download
1
Embed Size (px)
DESCRIPTION
Prezentacja z Techcamp#10 Kraków (www.techcamp.pl), 2013-06-19
Citation preview
Architektura serwera gier online
Maciej Mróz
› Gry online
• Krótki czas od koncepcji do wyjścia na rynek (3-6 miesięcy)
• Rozwój w znacznej części po release• Szybkie iteracje (czasem kilka update’ów dziennie)• Ciągła analiza zachowania użytkowników• A/B testing
• Wiele platform klienckich• Desktopy, tablety, telefony
• Małe (5-10 osób), niezależne zespoły produktowe• Wiele gier rozwijanych i utrzymywanych równolegle
• Złożona warstwa serwerowa
› Serwery – całkiem inne problemy
• System rozproszony• Wiele równorzędnych instancji serwerów• Asynchroniczna komunikacja
• Wielowątkowe „od zawsze”• Programowanie współbieżne jest trudne (a mutexy to zło!)
• Nieprzewidywalne obciążenie• Skalowalnośd trzeba brad pod uwagę od samego początku
• Znacznie mniejsza tolerancja na błędy w kodzie • Jeśli coś się może zepsud, to w koocu się zepsuje• Szansa 1 na milion w serwerze oznacza zdarzenie pewne
• Infrastruktura jest zawodna
› Nasze rozwiązanie
• Platforma serwerowa rozwijana przez dedykowany zespół jako wewnętrzny produkt
• Rozwiązuje problemy wymagające specjalistycznej wiedzy lub powtarzalne• Load balancing, failover, komunikacja z bazami danych ...• Usługi specjalne (leaderboardy, listy przyjaciół, autentykacja, systemy
płatności ...)
• Logika gry odseparowana od reszty serwera• Rozwijana przez zespół tworzący grę jednocześnie z rozwojem klienta• Aby zrobid działającą grę, nie trzeba znad detali serwera
• W dużym stopniu ustandaryzowane środowisko
› Elementy architektury
› Skalowalnośd
• Stawianie nowej instancji serwera• Autokonfiguracja (bottom → up)• Rejestracja w usłudze nodebalancer
• Gaszenie instancji• Transfer stanów gry na inne aktywne instancje• Z reguły niewidoczne dla użytkowników
• W 100% zautomatyzowane, także dla instancji web
• DynamoDB jako baza klucz -> wartośd
• Serwisy backendowe nie skalują się automatycznie
› Logika gry
• Uproszczony actor model (http://en.wikipedia.org/wiki/Actor_model)• Serwer nie jest bezstanowy!• Logika gry przetwarza i emituje wiadomości• Komunikacja wyłącznie asynchroniczna• Gwarantowana kolejnośd przesyłania komunikatów od A do B
• Brak bezpośredniej komunikacji z bazą danych• Binarne bloby na poziomie bazy danych stanów gry• Kompresja/dekompresja w locie
• Brak sztywnego protokołu sieciowego, można zakodowad co się chce jako tekst• Format jest teoretycznie dowolny, ale używamy JSON
• Serwer nie rozumie logiki• „czarna skrzynka” ładowania w czasie działania serwera przez dlopen()• Może byd przeładowana w locie!
› API logiki (przykłady)
Interakcje z serwerem:
virtual bool on_init_global_config(DWORD64 timestamp, const string & global_config) = 0;
virtual void on_cleanup() = 0;
virtual bool on_put_gamestate(DWORD64 timestamp, INT32 gamestate_ID, const string & gamestate) = 0;
virtual void on_get_gamestate(INT32 gamestate_ID, string & gamestate, bool server_closing,
bool logic_reload) = 0;
virtual void on_erase_gamestate(INT32 gamestate_ID) = 0;
Przetwarzanie komunikatów:
virtual void handle_player_message(DWORD64 timestamp, INT32 user_id, INT32 gamestate_ID,
const std::string &message, const std::string ¶ms) {};
virtual void handle_friend_message(DWORD64 timestamp, INT32 user_id, INT32 gamestate_ID,
const std::string &message, const std::string ¶ms) {};
virtual void handle_system_message(DWORD64 timestamp, INT32 gamestate_ID,
const std::string &message, const std::string ¶ms, std::string & output) {};
virtual void handle_gamestate_message(DWORD64 timestamp, INT32 gamestate_ID,
const std::string &message, const std::string ¶ms) {};
› API serwera (przykłady)
Funkcjonalności udostępniane dla logiki:
virtual void SendMessage(int user_id,int gamestate_ID, const std::string &message,
const std::string ¶ms) = 0;
virtual void SendBroadcastMessage(int exclude_ID, int gamestate_ID, const std::string &message,
const std::string ¶ms) = 0;
virtual void RequestLeaderboard(int user_id, const string & leaderboard_key,
DWORD64 leaderboard_subkey) = 0;
virtual void UpdateLeaderboard(int user_id, const string & leaderboard_key,
DWORD64 leaderboard_subkey, vector<INT32> & scores) = 0;
virtual void SendMessageToGamestate(int gamestate_ID, const std::string & command,
const std::string & params) = 0;
virtual void SubmitAnalyticsEvent(const char * Game_ID, DWORD64 Player_ID,
const char * event_name_with_category,
const std::map<string, string> & options) = 0;
› Logika gry (przykłady)
Lua
C++
› Global Conflig
› Przykładowy stan gry
› Model developmentu
• Teamy są od siebie odizolowane, zarówno lokalnie jak i na produkcji• Zależności zewnętrzne dostępne poprzez API• Jeden „tech team” rozwijający platformę, działający jako grupa wsparcia dla
poszczególnych projektów
› Środowisko
• Lokalnie każdy zespół ma swój komplet wirtualnych serwerów• Co najmniej instancja www, serwer baz danych i serwer gier.• Ręcznie zarządzana wirtualizacja na kilku hostach KVM• Planujemy wdrożenie OpenStacka
• Wystawianie nowej wersji na środowisko lokalne jest automatyczne• Serwer Continuous Integration śledzi branch „dev”• Nowe wersje budowane wielokrotnie w ciągu dnia• Zepsute buildy mają priorytet
• Wystawianie na produkcję jest w 100% pod kontrolą zespołu• Serwer CI przygotowuje nową wersję na podstawie brancha
produkcyjnego• Aktywacja zmian na produkcji poprzez dedykowany panel administracyjny• Rollback pod jednym kliknięciem
› Panel administracyjny