Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Rozkład obciążenia pomiędzy kilka serwerów
Forum PHP.pl > Forum > PHP
matix
Hej,
Pytanie do nieco bardziej zaawansowanych osób, mających doświadczenie z projektowaniem bardziej skalowanych aplikacji, przez które przepływa większy ruch.

Do stworzenia mam aplikację www oraz jej odpowiednik programu na telefony do przeszkiwania pewnych dużych zasobów.
Nie jest to czysta praca bazodanowa, tylko będą jeszcze w jednym Requeście wykonywane bardziej skomplikowane czynności, dopiero potem będą wysyłane do użytkownika dane.

Aplikacja będzie na zasadzie połączenia się z innymi Api innych aplikacji, wykonania pewnych czynności, oraz zwrócenia wyniku użytkownikowi, więc w grę wchodzi także przepustowość łącza.

Zakładamy, że ruch przewidywana na tych 2 aplikacjach będzie naprawdę spory (nie ważne ile, chodzi mi o sposób elastycznego podejścia do problemu tak, aby przy coraz większej liczbie korzystań z aplikacji, można było ją coraz bardziej rozwijać).

I teraz pytanie: Jak najlepiej wykonać aplikację tak, aby można było ją jak najlepiej w przyszłości skalować?

Moja propozycja rozwiązania jest taka:

(Zakładam, że pracuję na Symfony2)
Potrzeba minimum 3 osobnych serwerów;

Odciążam aplikację główną - Ona będzie wykorzystywana tylko do trzymania bazy danych użytkowników(tu można dzielić na bazy danych w razie potrzeby w przyszłości, ale to bym na razie zostawił).
Następnie tworzę ApiBundle, które będzie komunikowało się z innymi serwerem (REST) i otrzymywało odpowiedź w postaci JSON lub XML.

Co będzie robił ten drugi serwer? Ano, będzie jakby load balancerem, tz: będzie odpytywał losowy serwer z puli które zostaną mu podane. Jak będzie to wyglądało w praktyce?

Użytkownik wchodzi na stronę, loguje się (lub rejestruje). Chce coś pobrać, więc wpisuje w wyszukiwarce zapytanie, które go interesuje. ApiBundle wysyła request do drugiego serwera, ten ma do dyspozycji np. 5 serwerów typu slave, losuje, że tym zadaniem zajmie się serwer np. 3 no i odpytuje go o dane. Serwer nr 3 mu je powinien do określonego czas zwrócić. Jeżeli tak zrobi to serwer drugi (master) zwraca odpowiedź już serwerowi pierwszemu.

Serwery wykonawcze (CASServer i jego serwery wykonawcze) będą prawdopodobnie programowane w języku Java w celu wykorzystania wielowątkowości - najlepiej chyba na zasadzie serwer nadsłuchujący TCP i klienci (Datagramy);

Przykład wyżej tyczy się oczywiście aplikacji webowej, natomiast w przypadku aplikacji mobilnej (Windows Mobile 8, C#) będzie to miało identyczne zastosowanie. Ze względu na to, że korzystamy z 2 platform(mobile, www) trzeba zrobić tak jakby CASServer, który będzie rozdzielał zadania na poszczególne już stacje wykonawcze.

Na koniec mały preview rozwiżania w postaci graficznej. Sory za wykorzystanie w tym celu USE-CASE, ale nie miałem lepszego pomysłu na szybko:)


Będę wdzięczny za sugestie, inne podejścia do rozwiązania problemu smile.gif
LamaMASTER
Opcja kiepska, co jak padnie główny serwer z bazą danych? Rozłożenie dalej nie pomoże ci w ogóle, jako że serwer główny nawet nie przekieruje requesta...

Najprościej jest to zrobić tak:
1. Na DNSach głównej domeny masz wpisy do wszystkich serwerów matek (kilka serwerów do głównej aplikacji i baz danych),
2. Serwery matki synchronizują swoje bazy (coś w stylu Mutex),
3. Serwery matki odpytują co jakiś czas serwery SLAVE (te do requestów) i zapisują czasy w jakimś pliku,
4. W momencie wykonywania requesta wybierany jest serwer z najkrótszym zapisanym czasem i jeśli jest odpowiedź to leci request, jeśli nie ma (serwer leży) to leci request do następnego z listy (rekurencja). W ogóle co to za pomysł wysyłać request do losowego serwera, skoro zależy ci na optymalizacji i prędkości?

Ja jeszcze bym to uprościł, zamiast podziału master/slave, dać po prostu kilka serwerów, które będą obsługiwały i bazy i requesty.

W ogóle dziwnie się do tego zabierasz, dostałeś duże zlecenie i nie myślisz o optymalizacji, do tego jeszcze jako podstawa Symfony.
matix
Dzięki za odpowiedź.

Racja, trzeba by sprawdzać jeszcze bazę główną, czy nie padnie, ale tam nie będzie żadnych obliczeń, tylko z mojego założenia jednostkami obliczeniowymi będą bazy postawione na innych komputerach, więc wydaje mi się, że nawet wielki ruch nie powinien jakoś temu przeszkodzić.

Zdecydowałem się na zapytanie do losowego serwera, ponieważ w tym momencie, statystycznie, ruch powinien być rozłożony równomiernie po wszystkich komputerach (zakładając, że każdy klient wymaga tyle samo czasu/procesora na wykonanie zadania). Rozwiązanie podane przez Ciebie może i jest bardziej sensowne, ale nie koniecznie bardziej skuteczne (trzeba by to przetestować).

Cytat
W ogóle dziwnie się do tego zabierasz, dostałeś duże zlecenie i nie myślisz o optymalizacji, do tego jeszcze jako podstawa Symfony.

Nie, nie dostałem dużego zlecenia, bo nie pracuję jako freelancer. Projekt wykonuję sam dla siebie. Nie myślę o optymalizacji do końca, bo to jest początek projektu, a na tym etapie uważam, że lepiej jest przemyśleć dobrze strukturę aplikacji pod względem skalowności, zobaczyć jak się wszystko będzie zachowywać w miarę rozwoju projektu i następnie optymalizować krokami.
Symfony2 nie jest podstawą, jest to przykładowa "jednostka końcowa" od strony klienta - może to być web apka na sf2, może to być aplikacja desktopowa pod Mac OS X w Swingu a będzie to także aplikacja mobilna na Windows Phone.

Nic, przemyślę jeszcze sprawę, ale błąd w strukturze polegający na jednym serwerze głównym, który może paść jest trafiony. Dzięki.

Pozdrawiam,
LamaMASTER
Nie chodzi o to czy będzie ruch na bazach czy nie. Serwery w Polsce to jedna wielka katastrofa, możesz mieć stronę w samym HTMLu i padnie ci serwer nawet na 5 minut, ale padnie. W tym momencie cała twoja usługa nie będzie działać i to nie przez obciążenie, tylko zwykły problem z serwerem.

Stąd rozłożenie głównej domeny na minimum dwa serwery / dwie bazy to podstawa, dopiero potem możesz się bawić w myślenie o serwerach, które będą wykonywać najwięcej roboty.

Cytat
Zdecydowałem się na zapytanie do losowego serwera, ponieważ w tym momencie, statystycznie, ruch powinien być rozłożony równomiernie po wszystkich komputerach (zakładając, że każdy klient wymaga tyle samo czasu/procesora na wykonanie zadania). Rozwiązanie podane przez Ciebie może i jest bardziej sensowne, ale nie koniecznie bardziej skuteczne (trzeba by to przetestować).

Rozłożenie precyzyjnie równomierne (identycznie po serwerach) jest bez sensu. W większości zawsze zostaną wolne zasoby - niby o to chodzi, ale część serwerów będzie wolniej odpowiadać (pewnie nieznacznie, ale zawsze). W przypadku przekierowywania wg czasów, obciążasz najszybsze serwery, w końcu ich czasy się zmieniają i ruch idzie po następnych. W praktyce czasy będą się zmieniać co chwilę i ruch będzie rozłożony, tyle że inteligentnie.

Losowe wybieranie serwerów (twój pomysł) też nie załatwi równomiernego rozłożenia. Na to możesz liczyć poprzez rozłożenie DNS lub poprzez przekierowywanie każdego kolejnego klienta na serwery (po kolei, a nie losowo). Tutaj znowu w grę wchodzi który klient jakie obciążenie wygeneruje itd. więc znowu wracamy do pomysłu z zapisywaniem czasów (zapisywałem nawet czasy w portalu w stylu podbij.pl, tak aby odliczanie sekund do końca aukcji uwzględniało opóźnienia w przesyłaniu danych, a nie robiło przeskoków co jakiś czas i to sprawdzało się najlepiej).
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.