Spectra

Natywny klient desktopowy panelu Spectra na Windows i Linux, napisany w C#/.NET. Prawdziwe binarium z dostępem do systemu, nie opakowany Chromium. Ten sam widok co web, ale z natywną wydajnością i integracją z pulpitem.

TypAplikacja desktopowa
StackC# / .NET, Avalonia
PlatformyWindows, Linux
DystrybucjaSamodzielne binarium
RdzeńWspólny z panelem web
Spectra
TL;DR

Natywny klient administracyjny hostingu Spectra na Windows i Linux, zbudowany w C#/.NET na Avalonii. Ten sam obraz co panel web, ale jako prawdziwe binarium spięte wprost z rdzeniem platformy i jej ogromnym API frozcore/frozmod - z dostępem do systemu, natywną szybkością i logiką współdzieloną z resztą Spectry, a nie przepisaną drugi raz.

Wprowadzenie

Spectra to marka hostingu serwerów gier, dla której zbudowaliśmy pełne zaplecze panelowe. Ten case study dotyczy jednej, ale kluczowej części tej układanki: natywnego klienta desktopowego dla administratorów. To nie jest osobna aplikacja żyjąca obok panelu - to kolejna skóra na tym samym rdzeniu, rozmawiająca z tym samym backendem co wersja web. Żeby zrozumieć, dlaczego było to wyzwanie, najpierw trzeba zobaczyć, jak duży jest system pod spodem.

Klient desktopowy nie renderuje ładnych ekranów nad pustką. Stoi na pełnej platformie: provisioning serwerów, zarządzanie mocą, pliki, bazy danych, telemetria, rozliczenia i uprawnienia. Naszym zadaniem było dać administratorowi natywne okno na to wszystko - bez opakowanej przeglądarki i bez dublowania logiki, która i tak już żyła w panelu web.

Panel, w którym siedzi się cały dzień

Administrator serwerów gier nie zagląda do panelu raz na tydzień. Ma go otwartego przez osiem godzin obok konsoli, klienta gry i komunikatora. W takim trybie kolejna karta w przeglądarce to nie wygoda, tylko piąte koło u wozu: ginie w tłoku zakładek, nie ma własnej ikony na pasku, nie reaguje na skróty systemowe i nie widzi plików lokalnych.

Chcieliśmy dać ten sam widok co web, ale jako aplikację, która zachowuje się jak reszta programów na pulpicie. Jeden twardy warunek: bez opakowanego Chromium. Klient, który dokłada 200 MB pamięci na starcie tylko po to, żeby wyświetlić dokładnie to samo, mija się z celem, zanim zdąży się w pełni uruchomić. Skoro administrator ma tu spędzać większość dnia, aplikacja musi być lekka, natychmiastowa i „swoja" na jego systemie, a nie kolejnym oknem przeglądarki udającym program.

W liczbach

MetrykaWartość
Systemy z jednego koduWindows i Linux
Typowy ślad pamięci~40 MB
Wspólny rdzeń z panelem webjeden
Widoki spięte z APIdziesiątki

Czym właściwie jest Spectra pod spodem

Największym nieporozumieniem przy takim projekcie jest myślenie, że „to tylko panel". W rzeczywistości panel to cienka warstwa nad backendem, który robi ciężką robotę: uruchamia i zatrzymuje serwery gier, przydziela zasoby, trzyma bazy danych, streamuje logi i konsolę na żywo, pilnuje limitów i rozliczeń. Ten backend to rozbudowane API rodziny frozcore/frozmod - dziesiątki endpointów, zdarzenia w czasie rzeczywistym i model uprawnień, który decyduje, kto co widzi i co może zrobić.

Klient desktopowy musi rozmawiać dokładnie z tym samym API co panel web. Nie ma tu „uproszczonej wersji na desktop": jeśli administrator zmienia limit pamięci serwera albo restartuje instancję, robi to przez ten sam kontrakt, przez który robi to web. Dlatego zanim powstał choćby jeden ekran, trzeba było zrozumieć i ujarzmić skalę tego API - i to była realna część wyzwania, a nie sam wygląd okna.

i
Informacja

Konsola i strumień logów działają na żywo. To nie odświeżanie co kilka sekund, tylko ciągły strumień zdarzeń z backendu - klient desktopowy subskrybuje go tak samo jak web, więc administrator widzi wyjście serwera w tej samej chwili, w której ono powstaje.

Jeden rdzeń, dwie skorupy

Logika domenowa - autoryzacja, model serwera, komendy zasilania, strumień logów, mapowanie uprawnień na to API - żyje w jednej bibliotece .NET. Panel web i klient desktopowy to dwie skorupy nad tym samym rdzeniem, więc poprawka w regule uprawnień albo w obsłudze endpointu ląduje w obu miejscach naraz. Znika cała klasa błędów „na webie działa, na desktopie nie".

Warstwę widoku rysuje Avalonia. To nie webview - kontrolki renderują się wprost przez Skia, tą samą ścieżką na Windows i na Linuksie, więc aplikacja wygląda identycznie na obu. Przy okazji dostaje realny dostęp do systemu plików, schowka i powiadomień, czego opakowana strona nigdy nie miała.

Stos

WarstwaWybórPo co tak
Język i runtimeC# / .NETjeden język na logikę i UI, dobre narzędzia
Warstwa widokuAvalonia (Skia)natywny render, identyczny na Windows i Linux
Rdzeń domenowywspólna biblioteka .NETta sama logika i ten sam klient API co panel web
Warstwa siecitypowany klient frozcore/frozmodjeden kontrakt, web i desktop mówią tym samym
Dystrybucjaself-contained publishjedno binarium, bez instalowania runtime u klienta

Integracja z gigantycznym API

To była najcięższa część. Backend Spectry wystawia dziesiątki operacji: cykl życia serwera, konsola, pliki, bazy danych, harmonogramy zadań, kopie zapasowe, użytkownicy i uprawnienia, telemetria zasobów. Żeby klient desktopowy nie zamienił się w plątaninę wywołań, owinęliśmy całe API w jeden typowany klient w rdzeniu - z jednym miejscem na autoryzację, ponawianie i obsługę błędów.

1
Jeden typowany klient API

wszystkie endpointy frozcore/frozmod za jednym interfejsem, z autoryzacją i ponawianiem w jednym miejscu, żeby ani web, ani desktop nie powtarzały tej logiki.

2
Strumienie na żywo

konsola, logi i telemetria jako subskrypcje zdarzeń, a nie odpytywanie w pętli; ten sam mechanizm co w panelu web.

3
Model uprawnień przy wejściu

to, co administrator może zobaczyć i zrobić, wynika z tych samych reguł co na webie, liczonych po stronie rdzenia, a nie „na oko" w UI.

4
Mapowanie na natywne widoki

odpowiedzi API trafiają wprost do natywnych kontrolek Avalonii, bez pośrednika w postaci DOM-u.

➜
Wskazówka

Owinięcie całego API w jeden klient w rdzeniu opłaciło się podwójnie: zmiana kontraktu po stronie backendu to jedna poprawka w bibliotece, którą web i desktop dostają tym samym commitem. Zero rozjazdu wersji, zero „a u mnie działa".

Wydajność i natywność

Skoro warunkiem brzegowym było „bez opakowanego Chromium", wydajność nie była dodatkiem, tylko celem. Avalonia rysuje interfejs bezpośrednio, bez silnika przeglądarki w środku, więc binarium z pełnym panelem waży ułamek tego, co ważyłby ten sam widok w Electronie, a startuje w ułamku sekundy.

Ślad pamięci na starcie (orientacyjnie, MB)

Klient Avalonia
40
Ten sam widok w Electronie
240

Do tego dochodzi to, czego przeglądarka nigdy nie dała: realny dostęp do systemu plików (pliki serwera wskazujesz wprost z dysku, bez wgrywania ich najpierw do przeglądarki), skróty systemowe, natywne powiadomienia i ikona na pasku zadań. Dla kogoś, kto siedzi w panelu cały dzień, to nie kosmetyka, tylko codzienna oszczędność czasu.

Jak to wszystko spięliśmy

Mając rdzeń z klientem API i skorupę na Avalonii, całość składała się w powtarzalny sposób. Kluczowe było to, żeby jedno źródło dawało dwa samodzielne binaria, realnie przetestowane na obu systemach, a nie tylko kompilujące się na oba.

1
Wycięcie rdzenia z panelu

autoryzacja, model serwera, komendy i klient API zostały odcięte od widoku web i przeniesione do osobnej biblioteki, która nie wie nic o tym, kto ją rysuje.

2
Skorupa na Avalonii

ten sam układ ekranów co web, ale w natywnych kontrolkach, spięty z rdzeniem przez zwykłe wywołania, nie przez HTTP do samego siebie.

3
Dwa cele w jednym przebiegu

publish na win-x64 i linux-x64 z tego samego źródła, każdy jako samodzielne binarium.

4
Test na obu systemach

to samo uruchamiane realnie na Windowsie i na Linuksie, z wpięciem do prawdziwego backendu, nie tylko kompilujące się na oba.

bash
dotnet publish -c Release -r win-x64 --self-contained true
dotnet publish -c Release -r linux-x64 --self-contained true

Jaki jest finalny efekt współpracy?

Administrator dostaje program, który startuje w ułamku sekundy, trzyma się paska zadań jak każda inna aplikacja i pokazuje dokładnie te dane co panel web - bo pod spodem to ten sam kod i to samo API. Skróty systemowe działają, pliki z dysku da się wskazać bez wgrywania ich najpierw do przeglądarki, konsola i logi lecą na żywo, a okno nie ginie w gąszczu zakładek. Zamiast „strony w oknie" administrator dostaje narzędzie, które czuje się jak część jego systemu.

Po stronie Spectry zysk jest równie konkretny i wieloletni. Jedna logika i jeden klient API zamiast dwóch utrzymywanych ręcznie w zgodzie oznaczają, że rozwój platformy nie mnoży się przez liczbę skórek. Nowa reguła uprawnień, nowy endpoint w backendzie czy zmiana w modelu serwera ląduje w webie i na desktopie tym samym commitem. Znika cała klasa błędów synchronizacji, a klient desktopowy przestaje być osobnym projektem do utrzymania.

Najważniejsze jest jednak to, że desktop nie jest „wersją light". Rozmawia z tym samym, pełnym API frozcore/frozmod co panel web, więc administrator nie musi wracać do przeglądarki po funkcje, których w aplikacji zabrakło - bo nie zabrakło żadnej. To jest różnica między opakowaną stroną a prawdziwym, natywnym klientem platformy: ten drugi rośnie razem z backendem, zamiast ciągnąć się za nim.

Więcej projektów

Inne realizacje z tej samej kategorii - zobacz, jak podchodzimy do podobnych wyzwań.

Masz podobny projekt?

Napisz do nas - wycena jest bezpłatna i wraca w godzinę.