Architektura „Next Train” – jak zbudować aplikację z danymi w czasie rzeczywistym
Niewidoczna architektura aplikacji transportowych
Stoisz na peronie i czekasz na pociąg. Otwierasz aplikację, sprawdzasz godzinę odjazdu i widzisz aktualny czas oczekiwania. Wygląda to prosto, ale za tą jedną liczbą kryje się skomplikowana infrastruktura techniczna.
Problem z danymi w czasie rzeczywistym
Aplikacje transportowe muszą dostarczać informacje, które zmieniają się co chwilę. Gdy użytkownik widzi nieaktualne dane, traci do nich zaufanie. Kluczowe pytanie brzmi: jak przesyłać aktualizacje szybko i nie obciążać przy tym całego systemu?
Lokalizacja użytkownika jako punkt wyjścia
Zanim aplikacja pokaże cokolwiek, musi wiedzieć, gdzie znajduje się użytkownik. Same współrzędne GPS nie wystarczą. Potrzebne jest mapowanie ich na konkretne stacje. Do tego służą mechanizmy reverse geocoding oraz szybkie wyszukiwanie najbliższych punktów.
Zamiast sprawdzać odległość do każdej stacji w mieście, stosuje się struktury danych typu GeoHash. Dzielą one przestrzeń na siatkę i ograniczają wyszukiwanie do wybranych obszarów.
Warstwy bazy danych
Dane transportowe mają dwa wymiary: przestrzenny i czasowy. Rozkłady jazdy zmieniają się rzadko, ale pozycja pojazdu aktualizuje się co sekundę. Dlatego systemy rozdzielają informacje na trzy części:
- Dane statyczne (stacje, trasy, rozkłady) przechowywane w PostgreSQL
- Dane bieżące (opóźnienia, pozycje) trzymane w Redis
- Strumienie zdarzeń (awarie, zmiany) obsługiwane przez Kafka lub RabbitMQ
Taki podział pozwala na agresywne cache'owanie części statycznych i jednoczesne szybkie aktualizowanie danych żywych.
Optymalizacja komunikacji z aplikacją
Wysyłanie pełnych danych przy każdym zapytaniu byłoby nieefektywne. Dlatego stosuje się aktualizacje różnicowe — przesyłane są tylko zmiany od ostatniego odpytania. Dodatkowo używa się lżejszych formatów niż JSON oraz cache'owania na poziomie regionów.
WebSocket czy polling?
Nie zawsze WebSocket jest najlepszym rozwiązaniem. Przy wyszukiwaniu najbliższego połączenia wystarczy odpytywanie co kilka sekund. Natomiast przy śledzeniu konkretnego pojazdu w czasie rzeczywistym połączenie WebSocket daje zauważalną różnicę w szybkości.
Wymagania infrastrukturalne
Aplikacje transportowe należą do usług krytycznych. Muszą działać nawet przy awarii jednego centrum danych. Potrzebują więc redundancji, mechanizmów łagodnej degradacji oraz limitowania zapytań. Ważne jest też monitorowanie, które wykryje przestarzałe dane zanim zauważą to użytkownicy.
Gdzie jeszcze przydają się te rozwiązania
Podobne wyzwania mają systemy e-commerce z aktualizacją stanów magazynowych, aplikacje ridesharingowe oraz dashboardy IoT. We wszystkich przypadkach chodzi o połączenie danych statycznych z informacjami zmieniającymi się dynamicznie.
Znaczenie domeny i hostingu
Przy budowie takiej aplikacji liczy się nie tylko kod. Ważny jest wybór domeny — powinna być krótka i łatwa do zapamiętania. Konfiguracja DNS musi wspierać failover między regionami, a SSL nie powinien wprowadzać opóźnień. Hosting powinien dobrze współpracować z CDN oraz umożliwiać integrację z Redis i Kafka.
Jeśli budujesz aplikację, która wymaga niskich opóźnień i niezawodności, warto zadbać o infrastrukturę już na etapie wyboru domeny i hostingu.