Jaki jest najlepszy sposób zaprojektowania strony internetowej, aby była wysoce skalowalna?


35

W przypadku witryn, które muszą być wysoce skalowalne, takich jak sieci społecznościowe, takie jak Facebook, jaki jest najlepszy sposób zaprojektowania witryny?

  1. Czy powinienem mieć usługę internetową, której strona wysyła w celu uzyskania potrzebnych danych?

    lub

  2. Czy witryna powinna bezpośrednio sprawdzać bazy danych? (można to zrobić za pomocą wbudowanych konstruktów językowych do automatycznego wypełniania tabel itp.).

Wydaje mi się, że usługa internetowa jest lepszym rozwiązaniem, ponieważ zapewnia scentralizowany dostęp do danych, a takie rzeczy jak buforowanie itp. Stają się znacznie łatwiejsze do kontrolowania, ale co myślą inni?


Pojawia się również pytanie, jakiej architektury użyć (np. MVC lub podobnej).
Ivan

Nie wiedząc więcej o tym, co dokładnie zamierzasz uruchomić, bardzo trudno jest udzielić odpowiedzi, ale pamiętaj o „usługach w chmurze”, prawdopodobnie Twoja aplikacja pasuje do pewnego rodzaju aplikacji SaaS. (Jest scentralizowany).
deepcell

ogólnie rzecz biorąc powiedziałbym, nic szczególnego na myśli ..
Daniel

1
Zbuduj go w „chmurze” i poświęć dużo czasu na czytanie HighScalability.com.
Evan Plaice

Odpowiedzi:


37

Wow, to proste pytanie, na które można znaleźć wiele możliwych odpowiedzi. Bardziej wyraźna część pytania dotyczy tego, czy można bardziej skalować interfejs z bazą danych bezpośrednio, czy za pośrednictwem usługi internetowej. Ta odpowiedź jest prosta: bezpośrednio przeprowadź zapytanie do bazy danych. Przejście przez usługę internetową powoduje cały szereg opóźnień, które są całkowicie niepotrzebne dla kodu działającego za zaporą ogniową (ogólnie). Na przykład usługa sieci Web wymaga, aby jakiś komponent odebrał żądanie, przekształcił go z postaci szeregowej, wysłał zapytanie do bazy danych, serializował odpowiedź i zwrócił ją. Więc jeśli twój kod działa za zaporą ogniową, oszczędzaj sobie kłopotów i po prostu odpytaj bezpośrednio DB.

Skalowanie strony internetowej jest jednak znacznie wykraczające poza postawione na początku pytanie. Więc wybacz mi, jeśli wybiorę tutaj styczną, ale pomyślałem, że to może być przydatne, biorąc pod uwagę, że wspomniałeś w szczególności o Facebooku.

Polecam przeczytać o pracy i narzędziach stworzonych przez Brada Fitzpatricka (założyciela LiveJournal, a teraz Google). Kiedy współpracowałem z nim w Six Apart, oto kilka rzeczy, których się od niego nauczyłem, a także o architekturze LiveJournal, która uczyniła go tak skalowalnym.

  1. Używaj wąskich tabel bazy danych zamiast szerokich . To, co było w tym fascynujące, to wiedza o motywach architektury, która tworzyła system, który był łatwy i szybkiulepszone. Jeśli używasz szerokich tabel lub tabel, dla których każde pole lub właściwość jest kolumną w tabeli, gdy przyjdzie czas na uaktualnienie schematu bazy danych, na przykład dodanie nowej kolumny, system będzie musiał zablokować tabelę podczas schematu zmiana została wprowadzona. Podczas pracy w skali oznaczałoby to prostą zmianę schematu bazy danych, która mogłaby doprowadzić do dużej awarii bazy danych. Co oczywiście jest do bani. Z drugiej strony wąska tabela po prostu przechowuje każdą indywidualną właściwość powiązaną z obiektem jako pojedynczy wiersz w bazie danych. Dlatego jeśli chcesz dodać nową kolumnę do bazy danych, wszystko, co musisz zrobić, to wstawić rekordy do tabeli, co jest operacją nieblokującą. Ok, to jest małe tło, zobaczmy, jak ten model faktycznie tłumaczy w działającym systemie, takim jak LiveJournal.

    Załóżmy, że chcesz załadować 10 ostatnich pozycji dziennika na blogu danej osoby, i powiedzmy, że każda pozycja dziennika ma dziesięć właściwości. W klasycznym układzie szerokiej tabeli każda właściwość korelowałaby z kolumną w tabeli. Użytkownik zapyta następnie tabelę raz, aby pobrać wszystkie potrzebne dane. Kwerenda zwróciłaby 10 wierszy, a każdy wiersz zawierałby wszystkie potrzebne dane (np. WYBIERZ * Z pozycji ZAMÓW WEDŁUG LIMITU daty 10). Jednak w wąskim układzie tabel sytuacja wygląda nieco inaczej. W tym przykładzie faktycznie istnieją dwie tabele: pierwsza tabela (tabela A) przechowuje proste kryteria, według których chciałbyś wyszukiwać, np. Identyfikator wpisu, identyfikator autora, datę wpisu itp. Druga tabela (tabela B) następnie przechowuje wszystkie właściwości związane z wpisem. Ta druga tabela ma trzy kolumny: identyfikator_wpisu, klucz i wartość. Dla każdego wiersza w tabeli A będzie 10 wierszy w tabeli B (jeden wiersz dla każdej właściwości). Dlatego aby pobrać i wyświetlić ostatnie dziesięć wpisów, potrzebujesz 11 zapytań. Pierwsze zapytanie daje listę identyfikatorów pozycji, a następnie następne dziesięć zapytań pobiera właściwości związane z każdym z wpisów zwróconych w pierwszym zapytaniu.

    „Holy Moly!” mówicie: „jak, u licha, może być bardziej skalowalne ?!” To całkowicie sprzeczne z intuicją, prawda? W pierwszym scenariuszu mieliśmy tylko jedno zapytanie do bazy danych, ale w drugim „bardziej skalowalnym” rozwiązaniu mamy 11 zapytań do bazy danych. To nie ma sensu. Odpowiedź na to pytanie opiera się całkowicie na następnym punkcie.

  2. Użyj memcache swobodnie. Jeśli nie wiesz, Memcache jest rozproszonym, bezstanowym, opartym na sieci systemem buforowania o niskim opóźnieniu. Używają go Facebook, Google, Yahoo i niemal każda popularna i skalowalna strona internetowa na świecie. Został wynaleziony przez Brada Fitzpatricka częściowo, aby pomóc zrównoważyć narzut bazy danych związany z projektem bazy danych wąskiej tabeli. Spójrzmy na ten sam przykład, co omówiony w punkcie 1 powyżej, ale tym razem wprowadzimy memcache.

    Zacznijmy, gdy użytkownik po raz pierwszy odwiedzi stronę i nic nie będzie w pamięci podręcznej. Zaczynasz od zapytania tabeli A, która zwraca identyfikatory 10 pozycji, które chcesz wyświetlić na stronie. Dla każdego z tych wpisów następnie przeszukujesz bazę danych, aby uzyskać właściwości związane z tym wpisem, a następnie użycie tych właściwości stanowi obiekt, z którym Twój kod może się połączyć (np. Obiekt). Następnie przechowujesz ten obiekt (lub szeregową postać tego obiektu) w memcache.

    Za drugim razem, gdy ktoś ładuje tę samą stronę, zaczynasz w ten sam sposób: przeszukując tabelę A, aby wyświetlić listę identyfikatorów wpisów, które wyświetlisz. Do każdego wpisu najpierw przejdź do memcache i powiedz „czy masz wpis X w pamięci podręcznej?” Jeśli tak, to memcache zwraca obiekt wejściowy do Ciebie. Jeśli nie, musisz ponownie wykonać zapytanie do bazy danych, aby pobrać jej właściwości, utworzyć obiekt i schować go w pamięci podręcznej. Przez większość czasu, gdy ktoś odwiedza tę samą stronę, jest tylko jedno zapytanie do bazy danych, wszystkie inne dane są następnie pobierane bezpośrednio z pamięci podręcznej.

    W praktyce większość LiveJournal zdarzyła się w ten sposób, że większość danych systemu, szczególnie te mniej zmienne, były buforowane w memcache, a dodatkowe zapytania do bazy danych potrzebne do obsługi schematu wąskiej tabeli zostały prawie całkowicie zrównowa one.

    Ten projekt znacznie ułatwił rozwiązanie problemu związanego ze złożeniem listy postów powiązanych ze wszystkimi znajomymi w strumień lub „ścianą” .

  3. Następnie rozważ podzielenie bazy danych na partycje. Model omówiony powyżej ujawnia jeszcze jeden problem, a mianowicie wąskie tabele będą zwykle bardzo duże / długie. Im więcej wierszy w tych tabelach, tym trudniejsze stają się inne zadania administracyjne. Aby to zrównoważyć, rozsądne może być zarządzanie rozmiarem tabel poprzez partycjonowanie tabel w taki sposób, aby klastry użytkowników były obsługiwane przez jedną bazę danych, a inny klaster użytkowników obsługiwany był przez oddzielną bazę danych. To rozkłada obciążenie bazy danych i utrzymuje wydajność zapytań.

  4. Wreszcie potrzebujesz niesamowitych indeksów. Szybkość twoich zapytań będzie zależeć w dużej mierze od tego, jak dobrze indeksowane są tabele twojej bazy danych. Nie będę spędzał zbyt dużo czasu na omawianiu indeksu, poza tym, że mówię, że to bardzo przypomina system katalogów gigantycznych kart, aby usprawnić znajdowanie igieł w stogu siana. Jeśli używasz mysql, zalecam włączenie dziennika powolnych zapytań, aby monitorować zapytania, których wypełnienie zajmuje dużo czasu. Kiedy zapytanie pojawi się na twoim radarach (np. Ponieważ jest wolne), dowiedz się, jaki indeks musisz dodać do tabeli, aby go przyspieszyć.

„Dziękuję za całe to wspaniałe tło, ale cholera, to dużo kodu, który będę musiał napisać.”

Niekoniecznie. Napisano wiele bibliotek, które sprawiają, że interfejs z memcache jest naprawdę łatwy. Jeszcze inne biblioteki skodyfikowały cały proces opisany powyżej; Data :: ObjectDriver w Perlu jest właśnie taką biblioteką. Jeśli chodzi o inne języki, będziesz musiał przeprowadzić własne badania.

Mam nadzieję, że ta odpowiedź była pomocna. To, co stwierdziłem częściej niż nie, to to, że skalowalność systemu często sprowadza się coraz mniej do kodu, a coraz bardziej do solidnego przechowywania danych i strategii zarządzania / projektu technicznego.


3
+1 Naprawdę uwielbiam to Wow, to proste pytanie, na które ogromny wybór możliwych odpowiedzi.
Pankaj Upadhyay

1
Całkowicie nie zgadzam się z „zapytaniem bezpośrednio do bazy danych”. Wspominasz partycjonowanie bazy danych w celu zwiększenia wydajności, gdy łatwiej byłoby zaimplementować architekturę single-master multi-slave z interfejsem API. Zaletą oddzielenia DB od aplikacji jest to, że warstwa API może dystrybuować żądania w dowolny sposób. Interfejs API to abstrakcja, która pozwala zmienić podstawową implementację i / lub ponownie wykorzystać dane bez uszkodzenia aplikacji.
Evan Plaice

1
(ciąg dalszy) Serializacja zawsze spowoduje narzut, ale tylko w warstwie API, która najprawdopodobniej będzie składać się z wielu instancji działających jednocześnie. Jeśli martwisz się szybkościami przesyłania przez drut, przekonwertuj na JSON, a najprawdopodobniej i tak zostanie skompresowany za pomocą gzip. Najłatwiejszy wzrost wydajności można uzyskać, gdy praca jest przekazywana z serwera do klienta. Ważnym pytaniem, które należy zadać, jest to, czy wolisz rozprowadzać żądania w aplikacji czy na poziomie serwera? Który łatwiej jest powielić?
Evan Plaice,

1
@EvanPlaice - Świetne informacje na temat ponownego wykorzystywania i zmiany implementacji logiki usługi podczas korzystania z usług. Ponadto - infrastruktura pamięci podręcznej może być również używana przez usługi zamiast bezpośrednich wywołań bazy danych.
Ashish Gupta

1
@AshishGupta Dokładnie, jedyną różnicą w dzieleniu danych na osobne usługi jest to, co otrzymuje użytkownik. Zamiast tego gromadzić zawartość HTML + na serwerze. Użytkownik otrzymuje dane i HTML oddzielnie, a przeglądarka klienta obsługuje ponowny montaż. Dzięki danych jako oddzielnej usłudze staje się również możliwe udostępnienie ich aplikacjom mobilnym lub innym klientom niebędącym przeglądarkami internetowymi (np. Aplikacje smart tv).
Evan Plaice,

13

W przypadku witryn, które muszą być wysoce skalowalne, takich jak sieci społecznościowe, takie jak Facebook, jaki jest najlepszy sposób zaprojektowania witryny?

Zmierzyć.

Myślałem, że ...

Zła polityka.

Rzeczywisty pomiar jest wymagany.


Wskaźniki ilościowe FTW.
bhagyas

1
Ok ... co jest po pomiarze?
Pacerier

9

Skalowalność nie jest funkcją konkretnych strategii implementacyjnych, ale raczej zaprojektowaniem architektury aplikacji, aby warstwa dostępu do danych mogła ewoluować bez masowego refaktoryzacji i przepisywania.

Ważną techniką budowania skalowalnego systemu jest zrozumienie wymagań dotyczących dostępu do danych na wysokim poziomie i zbudowanie wokół nich umowy dotyczącej interfejsu. Na przykład może być wymagane uzyskanie jednego użytkownika lub wyświetlenie 50 zdjęć opublikowanych ostatnio przez dowolnego użytkownika .

Niekoniecznie potrzebujesz kanału sieciowego między logiką biznesową aplikacji a logiką dostępu do danych; pośrednie wywołanie metody z jedną metodą na operację logiczną wystarczy, aby rozpocząć.

Zacznij od tych metod dostępu do danych tak prosto, jak to możliwe. Bardzo trudno jest przewidzieć, gdzie będą występować problemy z wydajnością, dopóki aplikacja nie obsługuje rzeczywistych wzorców użytkowania i nie gromadzisz danych o tym, gdzie masz wąskie gardła.

Dzięki dobrze zdefiniowanemu interfejsowi dostępu do danych możesz rozwijać swoją implementację dostępu do danych bez wprowadzania szerokich zmian w całej aplikacji. Możesz także zdecydować się na przejście na architekturę usług sieciowych w sposób przejrzysty zgodnie z logiką biznesową.

Wiele z powyższych odpowiedzi zawiera świetne porady, jak postępować po wykryciu wąskich gardeł wydajnościowych, ale jeśli zastosujesz je zbyt wcześnie, możesz zostać zahamowany przez złożoność kodu, zanim będziesz wiedział, czy ta złożoność jest w ogóle wymagana.


4

Opracuj prostą stronę internetową i pozwól jej osiągnąć pewien poziom ruchu. Wzdłuż linii nauczysz się, jak tworzyć skalowalne strony internetowe.

Dopóki nie napotkasz problemu, nie możesz wymyślić rozwiązania .

Zaufaj mi, gdy witryna będzie się aktualizować i będzie wymagać skalowania, na pewno będziesz wiedział, jak to zrobić. :-)


Dobry cytat !!!!!!!!!!
AmirHossein,

2

Przyjmuje się mądrość, że aplikacje internetowe powinny być projektowane domyślnie z trzema warstwami - warstwami WWW (prezentacji), aplikacji i bazy danych. Podział ten wynika z różnych wymagań na każdej z warstw - zazwyczaj wysokiej jakości dostęp do dysku / pamięci dla bazy danych, wysoki procesor / pamięć w warstwie aplikacji oraz wysokie zewnętrzne pasmo / pamięć / dyspersja geograficzna w warstwie internetowej. Warstwa aplikacji / bazy danych jest często łączona w jedną do znacznie później w cyklu życia aplikacji, ponieważ maszyny baz danych często mają tendencję do tworzenia ogromnych serwerów, które można zbudować tak, aby obsługiwały także wczesne ładowanie aplikacji.

Konkretna liczba warstw i odpowiednia architektura dla Twojej aplikacji nie musi jednak odpowiadać temu lub innemu modelowi.

Zaplanuj konieczność mierzenia i monitorowania całej aktywności w systemie. Zacznij od dwu- lub trzypoziomowego projektu i skoncentruj się na jego częściach, które podczas budowania będą wymagały jak największej ilości zasobów. Niech działająca aplikacja poprowadzi Twój projekt na tym poziomie. Im więcej informacji zbierzesz, tym bardziej dokładne i szczegółowe, tym lepsze decyzje dotyczące projektowania aplikacji w miarę jej wzrostu.

Wybierz platformę i architekturę, która pozwoli później przestawić / wprowadzić wymagane zmiany tak szybko i bezboleśnie, jak to możliwe. Nawet jeśli dostęp do danych / przechowywanie / przetwarzanie i przetwarzanie aplikacji są wykonywane w tym samym pliku wykonywalnym, jeśli są odpowiednio uwzględnione, na przykład nie będzie trudniej podzielić ich na dwie warstwy.


2

Każdy dodatkowy krok w łączeniu się z bazą danych to tylko narzut. Na przykład między UI -> Business Facade -> Business -> Data Access -> Databasei UI -> Databasedrugie podejście jest szybsze. Jednak im więcej kroków zostanie usuniętych, tym trudniej będzie utrzymać system i tym więcej będzie duplikacji. Wyobraź sobie, że piszesz kod niezbędny do pobrania listy znajomych w profilu, stronie głównej, stronie zarządzania potworami itp.

Dlatego należy zachować równowagę między wyższą wydajnością (co oczywiście wpływa bezpośrednio na wyższą skalowalność) a lepszą konserwacją .

Ale nie ograniczaj się do tematu połączenia z bazą danych, jeśli myślisz o tworzeniu wysoce skalowalnych stron internetowych. Weź również pod uwagę te elementy:

  1. Wybór odpowiedniej platformy (PHP jest szybszy ze względu na swój skryptowy charakter, ale ASP.NET musi w mgnieniu oka skompilować żądany plik, aby go przetworzyć i coś obsłużyć. Ponadto twierdzi się, że node.js jest bardziej skalowalny ze względu na jego wywołanie zwrotne) architektura oparta na )
  2. Korzystanie z architektury RESTful zamiast modelu usługi sieci Web (SOA)
  3. Używanie JSON do przesyłania danych zamiast XML (co powoduje, że do przesłania jest mniej bajtów)
  4. Postępowanie zgodnie ze wskazówkami dotyczącymi wydajności Yahoo
  5. Tematy dotyczące sieci i sprzętu, takie jak równoważenie obciążenia lub architektura warstw

2
Nie można powiedzieć, że PHP jest szybszy. Prawidłowo napisane aplikacje ASP.NET mogą w wielu przypadkach przewyższyć PHP. naspinski.net/post/AspNet-vs-php--speed-comparison.aspx
Andrew Lewis

+1 W rzeczywistości Twoim „prostym” rozwiązaniem będzie interfejs użytkownika -> Dostęp do danych -> Baza danych. 2 REST jest „łatwy”, ponieważ jest już wbudowany w większość przeglądarek. Nie ma potrzeby ponownego tworzenia koła API z odpowiedzią na polecenia. 3 JSON jest nie tylko mniejszy, ale wymaga mniejszej liczby kroków do serializacji-deserializacji, ponieważ nie trzeba sprawdzać encji HTML. Dobry towar.
Evan Plaice

1

Istnieją dwa podstawowe sposoby skalowania, zwiększania i zmniejszania.

Skalowanie w górę zastępuje maszynę mocniejszą. Skalowanie oznacza dodanie innej maszyny w celu wykonania pracy, którą wykonują istniejące maszyny.

Każda witryna o dużym natężeniu ruchu musi mieć możliwość skalowania. Architektura oprogramowania musi być wykonana w taki sposób, aby można było łatwo dodawać więcej maszyn w bardziej zajętym miejscu.

Zwykle oznacza to podzielenie aplikacji na warstwy, aby można było podłączyć i odtwarzać więcej serwerów na każdej warstwie.

Zrobiłbym opcję 1, miałbym usługę zamiast robić to bezpośrednio. Do tej pory można skalować tylko aplikację monolityczną.


0

Rozwijaj swoją witrynę za pomocą platformy technologicznej, która ma całkowicie zintegrowaną obsługę chmury.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.