Jaka jest najlepsza architektura serwerów dla gier w czasie rzeczywistym?

10

Zajmuję się tworzeniem gry w czasie rzeczywistym, która powinna pomieścić tysiące graczy w czasie rzeczywistym (FPS, takie jak maksymalne opóźnienie 1s). Jaka byłaby do tego najlepsza infrastruktura?

Mój pomysł polegał na użyciu 2 klastrów serwerów - jednego dla końca serwera (cała strona obliczeniowa) i jednego dla końca bazy danych, gdzie moduł równoważenia obciążenia jest „odpowiedzialny” za każdy klaster. Jeden główny serwer odbierze żądania od użytkowników i odeśle adres IP odpowiedniego serwera, aby użytkownik mógł to zrobić.

Klaster bazy danych użyje replikacji bazy danych w celu zapewnienia spójności między bazami danych.

Powinien również istnieć geograficzny moduł równoważenia obciążenia - aby przypisał regionalny moduł równoważenia obciążenia każdemu użytkownikowi w celu uzyskania najlepszej odpowiedzi.

Używam .NET + MSSQL do gry.

Dzięki!

rzymski
źródło
2
Kiedy mówisz „infrastruktura”, masz na myśli oprogramowanie, sprzęt, usługi, czy po prostu chcesz, abyśmy skrytykowali Twój istniejący plan?
Tetrad
1
@Nate - planujemy zwiększyć skalę, a nie powielać - więc powinna być w pełni skalowalna.
roman
2
-1 ponieważ teddziuba.com/2008/04/im-going-to-scale-my-foot-up-y.html - Nie spełniasz żadnych wymagań dotyczących pojemności, mówisz, że gra nie jest dzielona na części, ale czy jest strefowa itp. Charakter optymalizacji wydajności - w tym skalowalności - wymaga określonych informacji i nie ma absolutnie najlepszej architektury.
1
Chciałbym przeformułować twoje pytanie na coś bardziej konkretnego. Co jest „najlepsze” w faktyczny, nie subiektywny sposób? Czy masz na myśli najłatwiejszą do skalowania, łatwiejszą w zarządzaniu, najłatwiejszą do uruchomienia, najszybszą czy co?
Kaczka komunistyczna
1
„Najłatwiej” jest również subiektywne. Najłatwiej dla kogo, w jakim czasie, z jakich zasobów? Wymiana stosów najlepiej działa z określonymi pytaniami - „Zbudowałem ten serwer przy użyciu LINQ i MSSQL, ale spadł on po 70 transakcjach na sekundę, oto moje dwie najlepsze transakcje, które stanowią 73% mojego czasu wykonywania, jak powinienem zwiększyć moją przepustowość? „

Odpowiedzi:

6

Nie ma najlepszej architektury bez wiedzy o swoich wymaganiach, np. rodzaj interakcji między postaciami, ile danych będzie trwałych i tak dalej.

Jeśli potrafisz poradzić sobie z 1 sekundowym opóźnieniem, prawdopodobnie możesz hostować 1000 graczy na jednym serwerze bez problemów - ale w rzeczywistości jest to sprzeczne z ideą FPS, ponieważ zazwyczaj wymagają one znacznie mniejszych opóźnień, np. mniej niż 100 ms. Ale system, który radzi sobie z dużymi opóźnieniami, może sobie pozwolić na zrobienie wszystkiego poprzez przekazywanie wiadomości, co sprawia, że ​​spójność jest dość prosta. Podanie logiki jest dość proste, to znaczy - złożona logika staje się jeszcze gorsza, gdy zamienisz ją w system oparty na komunikatach, a nie w systemie z zablokowanymi obiektami - ale wszystko zależy od potrzeb twojej aplikacji.

Podobnie, jeśli nie utrwalasz dużej ilości danych, wcale nie potrzebujesz maszyny bazy danych, ale nie wiedząc o tym, trudno powiedzieć. Jeśli utrzymujesz małe ilości danych i być może robisz to dopiero pod koniec turnieju lub czegoś innego, znowu nie potrzebujesz osobnej bazy danych, a na pewno nie ich klastra. Z drugiej strony, jeśli nie upierasz się dużo, ale dużo czytasz, to właśnie tam mogą Ci pomóc zreplikowane bazy danych - ale oznacza to również, że relacyjna baza danych może nie najlepiej pasować do twojego problemu. Często lepszym rozwiązaniem jest pamięć podręczna w pamięci. Podobnie, jeśli nie ma interakcji między znakami w stylu transakcji, to spójność staje się mniej ważna. (A jeśli jest tylko kilka takich transakcji, możesz uczynić je specjalnym przypadkiem.)

W rzeczywistości uważaj na przyjęcie RDBMS tylko dlatego, że jest to zrobione w dużych systemach. Chociaż osobiście zgadzam się na używanie ich w grach online, najlepiej przyjrzeć się twoim wymaganiom i wymyślić strategię trwałości na podstawie tego, zamiast wybierać preferowaną bazę danych, a następnie próbować dostosować ją za pomocą pamięci podręcznej i replikacji, aby dopasować ją do twojego app. Może się okazać, że wszystko, czego potrzebujesz, to możliwość raportowania offline, w którym to przypadku prawdopodobnie najlepiej jest rejestrować proces w tle z mechanizmu utrzymywania gry do zdalnego RDBMS gdzie indziej.

Kylotan
źródło
4

Zastrzeżenie: moje doświadczenie w programowaniu gier opiera się na grach dla pojedynczego gracza po stronie klienta, ale mam doświadczenie w aplikacjach internetowych (szczególnie na stosie Microsoft), więc z tego powodu pochodzę z tej odpowiedzi, czuję, że tyle by zastosuj, ale bez faktycznego przetestowania prawdziwego serwera gry trudno jest powiedzieć, jak będzie on obowiązywał, ale proszę bardzo. Wiedz o tym: nie wdrożyłem serwera gier, tylko aplikacje internetowe.

Sugerowałbym podejście dwupoziomowe. Warstwa bazy danych i warstwa „aplikacji”; z trzecim poziomem prezentacji (twoim klientem).

Relacyjne bazy danych świetnie sprawdzają się w wyszukiwaniu danych i są przyzwoite w pisaniu danych. Kluczem jest szeregowanie zapisów w bazie danych na porcje o zarządzalnym rozmiarze, które klaster może obsłużyć. Bardziej zaawansowane wersje (Centrum danych / Przedsiębiorstwo) programu SQL Server obsługują klastrowanie i replikację. Zacznę od zbudowania małego klastra i uruchomienia kilku zapytań, aby zobaczyć, jak to działa.

W warstwie aplikacji, jeśli wykonujesz „podział na strefy” lub coś podobnego, prawdopodobnie możesz uciec bez konfigurowania klastrów i po prostu skonfigurować serwer dla strefy. Jeśli twoje strefy stają się zbyt duże, możesz ustawić klaster dla każdej strefy.

Będziesz chciał zbudować proces serializacji do wysyłania danych z poziomu aplikacji -> poziom bazy danych. Kluczem do sukcesu jest prowadzenie wielu poziomów serializacji. Coś takiego :

  • Poziom 1: Zapisz w DB co X sekund, zawiera dane krytyczne:
    • Zdrowie gracza
    • Przedmioty gracza / Przetworniki
  • Poziom 2: Zapisz do DB co 2X sekund, zawiera średnie dane:
    • Lokalizacje graczy
    • Lokalizacje NPC
  • Poziom 3: Wszystko inne, tak rzadko, jak to możliwe

Dzięki temu twoje zapisy będą spójne i przewidywalne, w zależności od charakteru twojej gry, możesz mieć rzadkie zapisy w bazie danych. Kluczem do sukcesu jest uświadomienie sobie, że jeśli serwer aplikacji ulegnie awarii, będziesz musiał wrócić do trybu online ze stanu w bazie danych, więc serializowanie zapasów odtwarzacza co 90 minut może go zdenerwować.

Aby odczytać dane, należy załadować jak najwięcej do pamięci w warstwie aplikacji, jak to możliwe, a następnie upewnić się, że cały kod korzysta z tej puli pamięci, w tle można synchronizować pulę pamięci z bazą danych. Jak zauważa Joe, będą chwile, kiedy będziesz potrzebować transakcji w czasie rzeczywistym. Serializując większość zapisów, powinieneś nadal mieć wystarczającą liczbę operacji we / wy w bazie danych, aby w razie potrzeby przeprowadzać transakcje w czasie rzeczywistym, zakładając wystarczający sprzęt na serwerze / klastrze bazy danych.

Nate
źródło
-1, ponieważ właśnie wyrzuciłeś ACID i używasz bazy danych jako magazynu dużych zbiorów danych. W porządku, harmonogram dysku systemu Windows jest wystarczająco gówniany, co wciąż powoduje wzrost wydajności, i prawdopodobnie możesz wykonać pewne dokładne pomiary offline z danymi w nim zawartymi, ale nadal potrzebujesz ACID - tj. Bazy danych - do obsługi transakcji w samej grze, w czasie rzeczywistym (ish).
Choć w niewielkim stopniu, właśnie do tego dążyłem w ostatnim akapicie. Polecam trochę hybrydy, w której w miarę możliwości korzystasz z IN-Memory i bazy danych, jeśli to konieczne.
Nate,
Problem polega na tym, że przeleciałeś nad tym, co jest w pamięci, która jest całą inną bazą danych, i nie podałeś żadnego wskazówek, jak zaimplementować to, co jest rzeczywiście trudnym bitem.
To prawda, choć pytanie dotyczyło architektury dużego obrazu, a nie szczegółów implementacji.
Nate
To prawda, ale pominąłeś całą środkową warstwę. Czy jest to RDB o niskim opóźnieniu? ODB? Magazyn kluczy / wartości? Brak DB i rezygnacja z ACID? STM czy blokowanie? Szczerze mówiąc, bardzo trudno jest na to odpowiedzieć, ponieważ w pytaniu nie ma zbyt wielu informacji, ale cała ta odpowiedź na schemacie architektury polega na umieszczeniu dużej bańki na środku za pomocą „?” i podłącz do niego jeszcze dwie usługi, nie wypełniając właściwie „?” jest.