Wie kann eine Website am besten skalierbar gestaltet werden?

35

Wie lässt sich eine Website am besten gestalten, wenn sie hoch skalierbar sein muss, z. B. in sozialen Netzwerken wie Facebook?

  1. Sollte ich einen Webdienst haben, den die Site abfragt, um die benötigten Daten zu erhalten?

    oder

  2. Sollte die Site Datenbanken direkt abfragen? (Kann mit eingebauten Sprachkonstrukten durchgeführt werden, um Tabellen automatisch zu füllen usw.).

Ich würde denken, dass der Webdienst das bessere Design ist, da er zentralisierten Datenzugriff ermöglicht und Dinge wie Caching und dergleichen viel einfacher zu kontrollieren sind. Aber was denken andere?

Daniel
quelle
Es stellt sich auch die Frage, welche Architektur verwendet werden soll (wie MVC oder ähnliches).
Ivan
Ohne genau zu wissen, was Sie starten werden, ist es sehr schwierig, eine Antwort zu geben. Denken Sie jedoch an "Cloud-Dienste", wahrscheinlich passt Ihre Anwendung in eine Art SaaS-App. (Es ist zentralisiert).
Deepcell
Im Allgemeinen würde ich sagen, nichts Besonderes im Sinn ..
Daniel
1
Erstellen Sie es in der Cloud und verbringen Sie viel Zeit damit, HighScalability.com zu lesen.
Evan Plaice

Antworten:

37

Wow, das ist eine einfache Frage, die eine Vielzahl möglicher Antworten bietet. Im expliziteren Teil Ihrer Frage wird gefragt, ob die direkte oder die über einen Webdienst durchzuführende Schnittstelle mit Ihrer Datenbank skalierbarer ist. Diese Antwort ist einfach: Fragen Sie die Datenbank direkt ab. Durch das Durchlaufen des Webdienstes wird eine ganze Reihe von Wartezeiten hinzugefügt, die für Code, der (im Großen und Ganzen) hinter einer Firewall ausgeführt wird, völlig unnötig sind. Ein Webdienst erfordert beispielsweise, dass eine Komponente eine Anforderung empfängt, sie deserialisiert, die Datenbank abfragt, eine Antwort serialisiert und sie zurückgibt. Wenn Ihr Code also nur hinter einer Firewall ausgeführt wird, sparen Sie sich die Mühe und fragen Sie die Datenbank direkt ab.

Die Skalierbarkeit einer Website geht jedoch weit über die Frage hinaus, die Sie ursprünglich gestellt haben. Verzeihen Sie mir also, wenn ich hier etwas anfange, aber ich dachte, es könnte nützlich sein, wenn man bedenkt, dass Sie insbesondere Facebook erwähnt haben.

Ich würde empfehlen, dass Sie sich über die Arbeit und Tools informieren, die Brad Fitzpatrick (Gründer von LiveJournal und jetzt bei Google) erstellt hat. Als ich bei Six Apart mit ihm zusammengearbeitet habe, habe ich einige Dinge über die Architektur von LiveJournal gelernt, die es so skalierbar gemacht haben.

  1. Verwenden Sie im Gegensatz zu breiten Tabellen schmale Datenbanktabellen . Faszinierend dabei war, zu lernen, was diese Architektur motivierte und ein System schuf, das einfach und schnell waraufgerüstet. Wenn Sie breite Tabellen oder Tabellen verwenden, für die jedes Feld oder jede Eigenschaft eine Spalte in der Tabelle ist, muss das System die Tabelle beim Upgrade des Datenbankschemas sperren, z. B. durch Hinzufügen einer neuen Spalte Änderung wird implementiert. Wenn Sie im Maßstab arbeiten, würde dies bedeuten, dass eine einfache Änderung des Datenbankschemas zu einem großen Datenbankausfall führen könnte. Was offensichtlich scheiße ist. In einer engen Tabelle hingegen wird einfach jede einzelne Eigenschaft, die einem Objekt zugeordnet ist, als einzelne Zeile in der Datenbank gespeichert. Wenn Sie der Datenbank eine neue Spalte hinzufügen möchten, müssen Sie daher nur Datensätze in eine Tabelle einfügen. Dies ist eine nicht sperrende Operation. Ok, das ist ein kleiner Hintergrund. Lassen Sie uns sehen, wie dieses Modell tatsächlich in einem funktionierenden System wie LiveJournal übersetzt wird.

    Angenommen, Sie möchten die letzten 10 Journaleinträge in das Blog einer Person laden. Angenommen, jeder Journaleintrag verfügt über zehn Eigenschaften. In einem klassischen breiten Tabellenlayout würde jede Eigenschaft mit einer Spalte in einer Tabelle korrelieren. Ein Benutzer würde dann die Tabelle einmal abfragen, um alle benötigten Daten abzurufen. Die Abfrage würde 10 Zeilen zurückgeben und jede Zeile würde alle Daten enthalten, die sie benötigen (z. B. SELECT * FROM-Einträge ORDER BY-Datum LIMIT 10). Bei einem schmalen Tabellenlayout sieht das jedoch etwas anders aus. In diesem Beispiel gibt es zwei Tabellen: In der ersten Tabelle (Tabelle A) werden einfache Kriterien gespeichert, nach denen gesucht werden soll, z. B. die ID des Eintrags, die ID des Autors, das Datum des Eintrags usw. Eine zweite Tabelle (Tabelle B) speichert dann alle Eigenschaften, die einem Eintrag zugeordnet sind. Diese zweite Tabelle enthält drei Spalten: entry_id, key und value. Für jede Zeile in Tabelle A gibt es 10 Zeilen in Tabelle B (eine Zeile für jede Eigenschaft). Um die letzten zehn Einträge abzurufen und anzuzeigen, benötigen Sie daher 11 Abfragen. Die erste Abfrage enthält die Liste der Eintrags-IDs. Bei den nächsten zehn Abfragen werden die Eigenschaften abgerufen, die den einzelnen in der ersten Abfrage zurückgegebenen Einträgen zugeordnet sind.

    "Heiliger Moly!" Sie sagen: "Wie in aller Welt kann das skalierbarer sein ?!" Es ist völlig kontraintuitiv, oder? Im ersten Szenario hatten wir nur eine Datenbankabfrage, aber in der zweiten "skalierbareren" Lösung haben wir 11 Datenbankabfragen. Das macht keinen Sinn. Die Antwort auf diese Frage hängt vollständig von der nächsten Kugel ab.

  2. Verwenden Sie Memcache großzügig. Falls Sie sich dessen nicht bewusst waren, handelt es sich bei memcache um ein verteiltes, zustandsloses, netzwerkbasiertes Caching-System mit geringer Latenz. Es wird von Facebook, Google, Yahoo und nahezu jeder beliebten und skalierbaren Website auf dem Planeten verwendet. Es wurde von Brad Fitzpatrick teilweise erfunden, um den Datenbank-Overhead auszugleichen, der einem Datenbank-Design mit schmalen Tabellen innewohnt. Schauen wir uns das gleiche Beispiel an, wie oben in # 1 beschrieben, aber dieses Mal wollen wir memcache einführen.

    Beginnen wir, wenn ein Benutzer zum ersten Mal eine Seite besucht und sich nichts im Cache befindet. Sie beginnen mit der Abfrage der Tabelle A, die die IDs der 10 Einträge zurückgibt, die Sie auf der Seite anzeigen möchten. Für jeden dieser Einträge fragen Sie dann die Datenbank ab, um die diesem Eintrag zugeordneten Eigenschaften abzurufen, und verwenden diese Eigenschaften dann als Objekt, mit dem Ihr Code eine Schnittstelle herstellen kann (z. B. ein Objekt). Anschließend speichern Sie dieses Objekt (oder eine serialisierte Form dieses Objekts) in memcache.

    Wenn jemand dieselbe Seite zum zweiten Mal lädt, beginnen Sie auf die gleiche Weise: Durch Abfragen von Tabelle A nach der Liste der angezeigten Eintrags-IDs. Für jeden Eintrag gehen Sie zuerst zu memcache und sagen: "Haben Sie den Eintrag #X im Cache?" Wenn ja, gibt memcache das Eintragsobjekt an Sie zurück. Wenn nicht, müssen Sie die Datenbank erneut abfragen, um ihre Eigenschaften abzurufen, das Objekt zu erstellen und im Memcache zu speichern. Wenn ein Benutzer zum zweiten Mal dieselbe Seite aufruft, gibt es meistens nur eine Datenbankabfrage. Alle anderen Daten werden dann direkt aus dem Memcache abgerufen.

    In der Praxis passierte für die meisten LiveJournal-Benutzer, dass die meisten Systemdaten, insbesondere die weniger flüchtigen Daten, im Memcache zwischengespeichert wurden und die zusätzlichen Abfragen an die Datenbank, die zur Unterstützung des Schemas für enge Tabellen erforderlich waren, so gut wie vollständig ausgeglichen wurden.

    Dieses Design hat das Lösen des Problems beim Zusammenstellen einer Liste von Posts, die mit all Ihren Freunden verknüpft sind, zu einem Stream oder einer "Wand" sehr viel einfacher gemacht.

  3. Als Nächstes sollten Sie Ihre Datenbank partitionieren. Das oben diskutierte Modell weist noch ein weiteres Problem auf, und das sind Ihre schmalen Tische, die dazu neigen, sehr groß / lang zu sein. Und je mehr Zeilen diese Tabellen enthalten, desto schwieriger werden andere Verwaltungsaufgaben. Um dies auszugleichen, ist es möglicherweise sinnvoll, die Größe Ihrer Tabellen zu verwalten, indem Sie die Tabellen auf eine bestimmte Weise partitionieren, sodass Benutzercluster von einer Datenbank und andere Benutzercluster von einer separaten Datenbank bedient werden. Dies verteilt die Last auf die Datenbank und sorgt für effiziente Abfragen.

  4. Schließlich brauchen Sie tolle Indizes. Die Geschwindigkeit Ihrer Abfragen hängt weitgehend davon ab, wie gut die Tabellen Ihrer Datenbank indiziert sind. Ich werde nicht zu viel Zeit darauf verwenden, zu diskutieren, was ein Index ist, außer zu sagen, dass es einem riesigen Kartenkatalogsystem sehr ähnlich ist, Nadeln in einem Heuhaufen effizienter zu finden. Wenn Sie MySQL verwenden, empfehle ich, das Protokoll für langsame Abfragen zu aktivieren, um zu überwachen, ob Abfragen ausgeführt werden, die lange dauern. Wenn eine Abfrage auf Ihrem Radar erscheint (z. B. weil sie langsam ist), finden Sie heraus, welchen Index Sie zur Tabelle hinzufügen müssen, um sie zu beschleunigen.

"Vielen Dank für all diese großartigen Hintergründe, aber das ist eine Menge Code, den ich schreiben muss."

Nicht unbedingt. Es wurden viele Bibliotheken geschrieben, die die Anbindung an den Memcache sehr einfach machen. Wieder andere Bibliotheken haben den gesamten oben beschriebenen Prozess kodifiziert; Data :: ObjectDriver in Perl ist eine solche Bibliothek. Für andere Sprachen müssen Sie Ihre eigenen Recherchen durchführen.

Ich hoffe, Sie fanden diese Antwort hilfreich. Was ich häufig festgestellt habe, ist, dass die Skalierbarkeit eines Systems häufig immer weniger auf Code und immer mehr auf eine solide Datenspeicherungs- und -verwaltungsstrategie / technisches Design zurückzuführen ist.

Byrne Reese
quelle
3
+1 Ich liebe dieses Wow, das ist eine einfache Frage, die eine Vielzahl von möglichen Antworten bietet.
Pankaj Upadhyay
1
Ich bin völlig anderer Meinung als "Datenbank direkt abfragen". Sie erwähnen das Partitionieren der Datenbank aus Gründen der Leistung, wenn es einfacher wäre, eine Single-Master-Multiple-Slave-Architektur mit einer API-Schnittstelle zu implementieren. Das Entkoppeln der Datenbank von der Anwendung hat den Vorteil, dass die API-Schicht die Anforderungen beliebig verteilen kann. Die API ist eine Abstraktion, mit der Sie die zugrunde liegende Implementierung ändern und / oder die Daten wiederverwenden können, ohne die Anwendung zu beschädigen.
Evan Plaice,
1
(Forts.) Durch die Serialisierung wird immer ein zusätzlicher Aufwand verursacht, jedoch nur in der API-Ebene, die höchstwahrscheinlich aus mehreren Instanzen besteht, die gleichzeitig ausgeführt werden. Wenn Sie sich Sorgen über die Übertragungsgeschwindigkeit über das Kabel machen, konvertieren Sie zu JSON und es wird höchstwahrscheinlich trotzdem mit gzip komprimiert. Die einfachsten Leistungssteigerungen werden erzielt, wenn die Arbeit vom Server auf den Client verlagert wird. Die wichtige Frage ist, ob Sie Anfragen lieber innerhalb der Anwendung oder auf Serverebene verteilen möchten. Was ist leichter zu duplizieren?
Evan Plaice,
1
@EvanPlaice - Hervorragende Punkte zur Wiederverwendbarkeit und zum Ändern der Implementierung der Dienstlogik bei der Verwendung von Diensten. Darüber hinaus kann die Cache-Infrastruktur auch von den Diensten anstelle von direkten Datenbankaufrufen verwendet werden.
Ashish Gupta
1
@AshishGupta Genau, der einzige Unterschied bei der Aufteilung der Daten auf einen separaten Dienst besteht darin, was der Benutzer erhält. Stellen Sie stattdessen den HTML + -Inhalt auf dem Server zusammen. Der Benutzer erhält Daten und HTML separat und der Client-Browser übernimmt den Zusammenbau. Mit Daten als separatem Dienst wird es auch möglich, sie für mobile Anwendungen oder andere nicht webbasierte Clients (z. B. Smart-TV-Apps) verfügbar zu machen.
Evan Plaice
13

Was ist der beste Weg, um Websites zu gestalten, die hoch skalierbar sein müssen, wie z. B. soziale Netzwerke wie Facebook?

Messen.

Ich würde das denken ...

Schlechte Politik.

Die tatsächliche Messung ist erforderlich.

S.Lott
quelle
Quantitative Metriken FTW.
Bhagyas
1
Ok ... also was ist nach der Messung?
Pacerier
9

Die Skalierbarkeit ist keine Funktion spezifischer Implementierungsstrategien, sondern das Entwerfen Ihrer Anwendungsarchitektur, damit sich die Datenzugriffsebene ohne massive Umgestaltung und Umschreibung entwickeln kann.

Eine wichtige Technik beim Aufbau eines skalierbaren Systems besteht darin, die Anforderungen für den Datenzugriff auf hoher Ebene zu verstehen und einen Schnittstellenvertrag zu erstellen. Beispielsweise müssen Sie möglicherweise einen Benutzer abrufen oder die 50 zuletzt von einem Benutzer geposteten Fotos auflisten .

Sie benötigen nicht unbedingt einen Netzwerkkanal zwischen der Geschäftslogik Ihrer Anwendung und der Datenzugriffslogik. Eine Methodenaufruf-Indirektion mit einer Methode pro logischer Operation reicht zum Starten völlig aus.

Machen Sie diese Datenzugriffsmethoden zunächst so einfach wie möglich. Es ist sehr schwer vorherzusagen, wo die Leistungsprobleme liegen werden, bis Ihre Anwendung echte Verwendungsmuster bedient und Sie Daten darüber sammeln, wo Sie Engpässe haben.

Durch eine gut definierte Datenzugriffsschnittstelle können Sie Ihre Datenzugriffsimplementierung weiterentwickeln, ohne umfassende Änderungen an Ihrer gesamten Anwendung vorzunehmen. Sie können auch entscheiden, transparent für Ihre Geschäftslogik auf eine Webservice-Architektur zu wechseln.

Viele der oben genannten Antworten enthalten einige gute Ratschläge zur Vorgehensweise, wenn Sie Leistungsengpässe entdeckt haben. Wenn Sie diese jedoch zu früh anwenden, kann die Komplexität Ihres Codes Sie überfordern, bevor Sie wissen, ob diese überhaupt erforderlich ist.

Martin Atkins
quelle
4

Entwickeln Sie eine einfache Website und lassen Sie sie ein gewisses Verkehrsniveau erreichen. In diesem Zusammenhang lernen Sie, wie Sie skalierbare Websites erstellen.

Solange Sie nicht mit dem Problem konfrontiert sind, können Sie keine Lösung finden .

Vertrauen Sie mir, wenn die Website erst einmal in Betrieb genommen und skaliert werden muss, werden Sie auf jeden Fall wissen, wie das geht. :-)

Pankaj Upadhyay
quelle
Gutes Zitat !!!!!!!!!!
AmirHossein
2

Es wird davon ausgegangen, dass Webanwendungen standardmäßig mit drei Ebenen entworfen werden sollten: Web- (Präsentations-), Anwendungs- und Datenbankebene. Diese Unterteilung ist auf unterschiedliche Anforderungen in den einzelnen Ebenen zurückzuführen - in der Regel Qualitätsfestplattenzugriff / -speicher für die Datenbank, hohe CPU / Arbeitsspeicher auf der App-Ebene und hohe externe Bandbreite / Arbeitsspeicher / geografische Streuung auf der Webebene. Die Anwendungs- / Datenbankschicht wird häufig erst viel später im Lebenszyklus der Anwendung zu einer zusammengeführt, da es sich bei den Datenbankmaschinen häufig um massive Server handelt, die auch für die frühe Auslastung der Anwendung gebaut werden können.

Die spezifische Anzahl von Schichten und die entsprechende Architektur für Ihre Anwendung müssen jedoch nicht mit diesem oder einem anderen Modell übereinstimmen.

Planen Sie die Notwendigkeit, alle Aktivitäten in Ihrem System zu messen und zu überwachen. Beginnen Sie mit einem zwei- oder dreistufigen Design und konzentrieren Sie sich auf die Teile, die beim Erstellen die meisten Ressourcen erfordern. Lassen Sie die ausgeführte Anwendung Ihr Design auf dieser Ebene leiten. Je mehr Informationen Sie sammeln und je genauer und detaillierter diese sind, desto bessere Entscheidungen können Sie über das Design der Anwendung treffen, während diese wächst.

Wählen Sie ein Framework und eine Architektur, die es Ihnen später ermöglichen, erforderliche Änderungen so schnell und schmerzlos wie möglich vorzunehmen. Selbst wenn Ihre Datenzugriffs- / Speicherungs- / Verarbeitungs- und Anwendungsverarbeitung in derselben ausführbaren Datei ausgeführt werden, ist es beispielsweise später nicht so schwierig, sie in zwei Ebenen aufzuteilen, wenn sie ordnungsgemäß berücksichtigt werden.

Blaubeerfelder
quelle
2

Jeder zusätzliche Schritt beim Herstellen einer Verbindung zur Datenbank ist nur ein Aufwand. Beispielsweise ist zwischen UI -> Business Facade -> Business -> Data Access -> Databaseund UI -> Databaseder zweite Ansatz schneller. Je mehr Schritte Sie jedoch entfernen, desto weniger wartbar wird Ihr System und desto mehr Duplikate werden angezeigt. Stellen Sie sich vor, Sie schreiben den erforderlichen Code, um die Liste der Freunde im Profil, auf der Startseite, auf der Seite zur Verwaltung von Freunden usw. abzurufen.

Daher sollten Sie hier ein Gleichgewicht zwischen höherer Leistung (was sich natürlich direkt auf die höhere Skalierbarkeit auswirkt) und besserer Wartbarkeit herstellen .

Sie sollten sich jedoch nicht auf das Thema Datenbankverbindung beschränken, wenn Sie über die Erstellung hochskalierbarer Websites nachdenken. Beachten Sie auch diese Punkte:

  1. Auswahl der richtigen Plattform (PHP ist aufgrund seiner Skripterstellung schneller, aber ASP.NET muss die angeforderte Datei sofort kompilieren, um sie zu verarbeiten und etwas bereitzustellen . Außerdem soll node.js aufgrund seines Rückrufs skalierbarer sein.) basierte Architektur )
  2. Verwenden der RESTful-Architektur anstelle des Web-Service-Modells (SOA)
  3. Verwenden von JSON für die Datenübertragung anstelle von XML (wodurch weniger Bytes übertragen werden müssen)
  4. Befolgen Sie die Leistungsrichtlinien von Yahoo
  5. Netzwerk- und Hardwarethemen wie Load Balancing oder Tier-Architektur
Saeed Neamati
quelle
2
Sie können nicht sagen, dass PHP schneller ist. Ordnungsgemäß geschriebene ASP.NET-Anwendungen können PHP in vielen Fällen übertreffen. naspinski.net/post/AspNet-vs-php--speed-comparison.aspx
Andrew Lewis
+1 Eigentlich wäre Ihre "einfache" Lösung, UI -> Datenzugriff -> Datenbank. 2 REST ist einfach, da es in den meisten Browsern bereits integriert ist. Das Befehlsantwort-API-Rad muss nicht neu erstellt werden. 3 JSON ist nicht nur kleiner, sondern erfordert auch weniger Schritte zum Serialisieren und Deserialisieren, da Sie nicht nach HTML-Entitäten suchen müssen. Gutes Zeug.
Evan Plaice
1

Es gibt zwei Hauptmethoden zum Skalieren: Vergrößern und Verkleinern.

Beim Hochskalieren wird eine Maschine durch eine leistungsstärkere ersetzt. Beim Skalieren wird eine weitere Maschine hinzugefügt, um die Arbeit zu erledigen, die vorhandene Maschinen ausführen.

Jede stark frequentierte Website muss skalierbar sein. Die Software-Architektur muss so gestaltet sein, dass mehr Maschinen hinzugefügt werden können, je geschäftiger die Site wird.

In der Regel bedeutet dies, dass die Anwendung in Ebenen aufgeteilt wird, sodass auf jeder Ebene mehrere Server angeschlossen und wiedergegeben werden können.

Ich würde Option 1 machen, einen Service haben, anstatt es direkt zu tun. Bisher können Sie nur eine monolithische Anwendung skalieren.

Jon Raynor
quelle
0

Entwickeln Sie Ihre Site mithilfe einer Technologieplattform, die die Unterstützung für die Cloud vollständig integriert hat.

Bhagyas
quelle