Załóżmy że stworzyłem aplikacje z której dziennie korzysta miliony użytkowników.
Jakie kroki muszę przedsięwziąć żeby mój backend był w stanie obsłużyć tak duży ruch?
REST API Springowe z tego co wiem obsługuje wiele zapytań na raz. Kwestia czy sobie poradzi?
Baza danych zapewne nierelacyjna + żeby obsługiwała asynchroniczne zapytania - MongoDB ?
Co jeszcze? Jakieś konkretne narzędzia na około?
No i load balancer i tyle instancji aplikacji ile będzie konieczne. Co do bazy to zależy jakie dane. Są klastry baz relacyjnych które to uniosą . No chyba że nie potrzebujesz ACID
- Clean code. Bardzo łatwo optymalizować czysty kod i bardzo trudno wyczyścić zoptymalizowany kod.
- Metryki, metryki, metryki.
Musisz wiedzieć gdzie są bottlenecki w aplikacji.
3 Zależnie od usecase:
- optymalizacja najwolniejszych zapytań SQL,
- optymalizacja hibernate (hypersystence optimizer)
- cache
- monitorowanie pul wątków np. Tomcatowej
- stronicowanie odpowiedzi z API
- CloudFlare, aby unikać DDOS
- Cache na HTTP np. etag
- Monitoring JVM. Garbage collector, JIT i ustawienie dobrych flag przy uruchomieniu,
- Optymalizacja pul połączeń do bazy danych,
- Circuit breaker / Retry tam gdzie potrzeba.
- Co do bazy to bym nie szalał. Każdy SQL daje radę dla 80% use case.
Z pytania wnioskuję, że nawet nie wiesz, że pod spodem jest serwer HTTP i na jakiej zasadzie on działa :) zacznijmy od tego, żeby ustalić na jaki ruch musisz się przygotować - najlepiej reads i writes per second w peeku ruchu. Możesz obsługiwać milion userów i mieć 10 rps, a możesz mieć i 10000. Do tego jaki jest czas odpowiedzi usługi (p99).
Po drugie, relacyjne bazy również się skalują. Np. taki Instagram korzysta z Postgresa.
Ponadto, abstrahując od Springa i JVM:
Charles_Ray napisał(a):
Z pytania wnioskuję, że nawet nie wiesz, że pod spodem jest serwer HTTP i na jakiej zasadzie on działa :) zacznijmy od tego, żeby ustalić na jaki ruch musisz się przygotować - najlepiej reads i writes per second w peeku ruchu. Możesz obsługiwać milion userów i mieć 10 rps, a możesz mieć i 10000. Do tego jaki jest czas odpowiedzi usługi (p99).
Po drugie, relacyjne bazy również się skalują. Np. taki Instagram korzysta z Postgresa.
I wcale nie jest powiedziane, że w zależności o szczegółów nie udźwignie tego jedna maszyna.
Jak na razie OP kol @Korges nam skąpi szczegółów
Robiłbym sobie nadzieję na dużą ilość req/s z jednej maszyny na architekturze asynchronicznej: jak Spring to Webflux (i czy koniecznie Spring?), może Ratpack (wydaje się dobry w kategorii Clean Code) i konkurencyjne rozwiązania. Wiedza teoretycznya, nie z własnych doświadczeń.
Pytanie jest czysto teoretycznie. Interesuje mnie road-mapa która wskazuje konkretne drogi wraz z rozrostem systemu. Generalnie odpowiedz na pytanie udzielona, czas się wziąć ja zgłębianie wiedzy :)
Zalezy jaki ruch.
- czy klienci moga miec dodatkowa logike czy tez uderzaja bezposrednio do apki?
- czy sa peaki?
- jaki jest maks czas odpowiedzi?
- ile danych srednio jest na request/response?
- jaki jest dopuszczalny procent requestow odrzuconych?
- czy mozna wymagac od klientow retrajow?
- czy dopuszczalny jest HTTP2?
- czy polaczenie musi byc szyfrowane?
- ile serwisow zewnetrznych trzeba wywolac srednio na request?
- czy dopuszczalna jest ewentualna spojnosc danych?
- jaki jest procent danych ktore sa statyczne?
- jaki procent danych moze byc keszowany?
Co do roadmapy to zainteresuj sie haslami NoSQL
, reactive
i Spring Cloud
.
- Zapomnij o tym że masz jeden serwer na backendzie. Od początku zakładaj że będzie to N maszyn, za load-balancerem, do tego być może z autoscalingiem.
- Nie napisałeś czy to będziesz np. w K8s wkładał - tam byś miał autoscaling za darmo.
- Baza danych, co najmniej 2 instancje - a najlepiej to mieć mały klaster (3 instancje).
- To co napisałem to nie po to żeby mieć 1M zapytań, to pewnie pierwszy lepszy laptop z serwerem w Go wyciągnie - tylko po to żeby mieć pole do manewru przy wdrażaniu i upgradach.
- Aplikacja powinna być napisana w sposób bezstanowy (nie trzymać niczego w pamięci), jeżeli sesja użytkownika jest potrzebna to dojdzie Redis (dobry też jako cache). Dzięki temu łatwo będzie to scalować i przerzucać użytkowników pomiędzy instancjami serwera gdy pojawi się nowa.
- Async lub RX to sposób na zwiększenie przepustowości jeżeli to musi być jeden serwer. Czytelność kodu ucierpi (choć niektórzy twierdzą że się poprawi), łatwość debugowania również.
- Bez podania innych info - czyli co to za apka, jakie gwarancje daje na backendzie (czy to sprzedaje bilety czy serwuje reklamy, zgubiony zapis w #1 jest bolesny, w #2 nie), czy ruch jest ciągły czy skokowy (bilety) ciężko ocenić. Generalnie to o co pytasz to zadanie dla architekta i to nie na dzień tylko raczej na tydzień pracy lub więcej.
Nie da się odpowiedzieć nie znając charakterystyki ruchu i serwisu. Jedyne generalne zasady to:
- bezstanowość tak bardzo jak się tylko da, dzięki temu możesz zrównoleglić aplikacje na wiele maszyn i postawic za load balancerem
- operacje na ścieżce krytycznej robisz bez interakcji z czymś co jest "wolne", więc np. nie strzelasz do bazy albo do zewnętrznych serwisów
Cała reszta zależy od tego co robisz. Potrzebujesz low-latency? Ile czasu trwa jeden request? Jak kosztowne obliczeniowo są operacje które realizuje ten system?