Qual è il modo migliore per progettare un sito Web in modo altamente scalabile?


35

Per i siti Web che devono essere altamente scalabili, come i social network come Facebook, qual è il modo migliore per progettare il sito Web?

  1. Dovrei avere un servizio web che il sito richiede per ottenere i dati di cui ha bisogno?

    o

  2. Il sito dovrebbe interrogare direttamente i database? (può essere fatto usando costrutti di linguaggio integrati per riempire automaticamente le tabelle ecc.).

Penso che il servizio web sia il miglior design in quanto consente l'accesso centralizzato ai dati e cose come la memorizzazione nella cache e simili diventano molto più facili da controllare, ma cosa ne pensano gli altri?


C'è anche la domanda su quale architettura usare (come MVC o simili).
Ivan,

Senza sapere di più su cosa esattamente stai per lanciare, è molto difficile dare la risposta, ma tieni presente i "servizi cloud", probabilmente la tua applicazione si adatta a una specie di app SaaS. (È centralizzato).
deepcell,

in generale direi, niente di particolare in mente ..
Daniel

1
Costruiscilo nel "cloud" e trascorri molto tempo a leggere HighScalability.com.
Evan Plaice,

Risposte:


37

Caspita, questa è una domanda semplice, che offre una vasta gamma di possibili risposte. La parte più esplicita della tua domanda ti chiede se è più scalabile interfacciarsi con il tuo database direttamente o attraverso un servizio web. Questa risposta è semplice: interrogare direttamente il database. Passare attraverso il servizio Web aggiunge un sacco di latenza che è completamente inutile per il codice che opera dietro un firewall (nel complesso). Un servizio Web, ad esempio, richiede che un componente riceva una richiesta, la deserializzi, interroghi il DB, serializzi una risposta e la restituisca. Quindi, se il tuo codice funziona tutto dietro un firewall, risparmia il problema ed esegui una query direttamente sul DB.

Rendere scalabile un sito Web va ben oltre la domanda che hai posto inizialmente. Quindi perdonami se vado su una tangente qui, ma ho pensato che potrebbe essere utile considerando che hai menzionato Facebook in particolare.

Ti consiglierei di leggere il lavoro e gli strumenti sviluppati da Brad Fitzpatrick (fondatore di LiveJournal e ora su Google). Quando ho lavorato con lui in Six Apart, ecco alcune delle cose che ho imparato da lui e sull'architettura di LiveJournal che l'ha resa così scalabile.

  1. Utilizzare tabelle di database ristrette anziché ampie . Ciò che è stato affascinante di questo è stato imparare ciò che ha motivato questa architettura, che stava creando un sistema facile e veloceaggiornato. Se si utilizzano tabelle larghe o tabelle per le quali ciascun campo o proprietà è una colonna nella tabella, quando arriva il momento di aggiornare lo schema del database, ad esempio aggiungendo una nuova colonna, il sistema dovrà bloccare la tabella mentre lo schema il cambiamento è implementato. Quando si opera su larga scala, ciò significherebbe che una semplice modifica allo schema del database potrebbe comportare un'interruzione del database di grandi dimensioni. Il che fa schifo ovviamente. Una tabella stretta d'altra parte memorizza semplicemente ogni singola proprietà associata a un oggetto come una singola riga nel database. Pertanto, quando si desidera aggiungere una nuova colonna al database, è sufficiente inserire i record INSERT in una tabella, che è un'operazione non bloccante. Ok, questo è un po 'di background, vediamo come questo modello si traduce effettivamente in un sistema funzionante come LiveJournal.

    Supponiamo che tu voglia caricare le ultime 10 voci del diario sul blog di una persona e supponiamo che ogni voce del diario abbia dieci proprietà. In un layout di tabella ampia classica, ogni proprietà sarebbe correlata a una colonna su una tabella. Un utente dovrebbe quindi interrogare la tabella una volta per recuperare tutti i dati di cui ha bisogno. La query restituirebbe 10 righe e ogni riga avrebbe tutti i dati necessari (ad es. SELEZIONA * DA voci ORDINA PER data LIMIT 10). In una tabella stretta, tuttavia, le cose sono leggermente diverse. In questo esempio in realtà ci sono due tabelle: la prima tabella (tabella A) memorizza semplici criteri per cui si vorrebbe cercare, ad esempio l'id della voce, l'id dell'autore, la data della voce, ecc. Una seconda tabella (tabella B) quindi memorizza tutte le proprietà associate a una voce. Questa seconda tabella ha tre colonne: entry_id, chiave e valore. Per ogni riga nella tabella A, ci sarebbero 10 righe nella tabella B (una riga per ogni proprietà). Pertanto, per recuperare e visualizzare le ultime dieci voci, sono necessarie 11 query. La prima query fornisce l'elenco degli ID delle voci, quindi le dieci query successive recuperano le proprietà associate a ciascuna delle voci restituite nella prima query.

    "Santo moly!" dici "come mai può essere più scalabile ?!" È totalmente controintuitivo, giusto? Nel primo scenario abbiamo appena avuto una query di database, ma nella seconda soluzione "più scalabile" abbiamo 11 query di database. Non ha senso. La risposta a questa domanda si basa interamente sul prossimo proiettile.

  2. Usa memcache liberamente. Nel caso in cui non si fosse a conoscenza, memcache è un sistema di memorizzazione nella cache distribuito, senza stato, a bassa latenza e basato sulla rete. È utilizzato da Facebook, Google, Yahoo e quasi tutti i siti Web popolari e scalabili del pianeta. È stato inventato da Brad Fitzpatrick in parte per aiutare a compensare l'overhead del database inerente a una progettazione di database a tabella ristretta. Diamo un'occhiata allo stesso esempio di cui al punto 1 sopra, ma questa volta introduciamo memcache.

    Cominciamo quando un utente visita per la prima volta una pagina e non c'è nulla nella cache. Si inizia interrogando la tabella A che restituisce gli ID delle 10 voci che si desidera visualizzare sulla pagina. Per ognuna di queste voci, si richiede quindi al database di recuperare le proprietà associate a quella voce e quindi l'utilizzo di tali proprietà costituisce un oggetto con cui il codice può interfacciarsi (ad esempio un oggetto). Quindi riponi quell'oggetto (o una forma serializzata di quell'oggetto) in memcache.

    La seconda volta che qualcuno carica la stessa pagina, inizi nello stesso modo: eseguendo una query sulla tabella A per l'elenco degli ID voce che verranno visualizzati. Per ogni voce, vai prima su memcache e dici "hai la voce #X nella cache?" Se sì, memcache ti restituisce l'oggetto di immissione. In caso contrario, è necessario interrogare nuovamente il database per recuperare le sue proprietà, costituire l'oggetto e riporlo in memcache. Il più delle volte, la seconda volta che qualcuno visita la stessa pagina c'è solo una query del database, tutti gli altri dati vengono quindi estratti direttamente da memcache.

    In pratica, ciò che alla fine è accaduto per la maggior parte di LiveJournal è che la maggior parte dei dati del sistema, in particolare i dati meno volatili, sono stati memorizzati nella cache di memcache e le query aggiuntive al database necessarie per supportare lo schema di tabelle ristrette erano quasi completamente compensate.

    Questo design ha fatto risolvere il problema connesso con l'assemblaggio di un elenco dei posti connessi con tutti i tuoi amici in un ruscello, o "muro" molto, molto più facile.

  3. Quindi, prendere in considerazione il partizionamento del database. Il modello discusso sopra presenta ancora un altro problema, e cioè i tuoi tavoli stretti tenderanno ad essere molto grandi / lunghi. E più righe hanno quelle tabelle, più diventano difficili le altre attività amministrative. Per compensare ciò, potrebbe avere senso gestire le dimensioni delle tabelle partizionando le tabelle in qualche modo, in modo che i cluster di utenti siano serviti da un database e un altro cluster di utenti sia servito da un database separato. Ciò distribuisce il carico sul database e mantiene efficienti le query.

  4. Infine, hai bisogno di indici fantastici. La velocità delle tue domande dipenderà in gran parte da quanto bene sono indicizzate le tabelle del tuo database. Non passerò troppo tempo a discutere di cosa sia un indice, se non per dire che è molto simile a un sistema di catalogo di carte giganti per rendere più efficiente la ricerca di aghi in un pagliaio. Se usi mysql, ti consiglio di attivare il registro delle query lente per monitorare le query che richiedono molto tempo per essere soddisfatte. Quando viene visualizzata una query sul radar (ad es. Perché è lenta), quindi capire quale indice è necessario aggiungere alla tabella per accelerarlo.

"Grazie per tutto questo fantastico background, ma santo crudele, è un sacco di codice che dovrò scrivere."

Non necessariamente. Sono state scritte molte librerie che rendono davvero semplice l'interfacciamento con memcache. Ancora altre biblioteche hanno codificato l'intero processo sopra descritto; Data :: ObjectDriver in Perl è proprio una libreria del genere. Per quanto riguarda le altre lingue, dovrai fare le tue ricerche.

Spero che tu abbia trovato utile questa risposta. Quello che ho scoperto più spesso è che la scalabilità di un sistema spesso si riduce sempre meno al codice, e sempre di più a una solida strategia di archiviazione e gestione dei dati / progettazione tecnica.


3
+1 Adoro davvero questo Wow, questa è una domanda semplice, a cui una vasta gamma di possibili risposte.
Pankaj Upadhyay,

1
Non sono completamente d'accordo con "interroga direttamente il database". Si menziona il partizionamento del database per prestazioni quando sarebbe più semplice implementare un'architettura multi-master single-master con un'interfaccia API. Il vantaggio del disaccoppiamento del DB dall'applicazione è che il livello API può distribuire le richieste nel modo desiderato. L'API è un'astrazione che consente di modificare l'implementazione sottostante e / o riutilizzare i dati senza interrompere l'applicazione.
Evan Plaice,

1
(cont) La serializzazione aggiungerà sempre un sovraccarico, ma solo nel livello API che molto probabilmente consisterà in più istanze in esecuzione contemporaneamente. Se sei preoccupato per le velocità di trasferimento attraverso il filo, converti in JSON e molto probabilmente sarà compresso con gzip. I guadagni di prestazione più facili possono essere trovati quando il lavoro viene trasferito dal server al client. La domanda importante da porsi è: preferiresti distribuire le richieste all'interno dell'applicazione o a livello di server? Qual è più facile da duplicare?
Evan Plaice,

1
@EvanPlaice - Ottimi punti sulla riutilizzabilità e modifica dell'implementazione della logica di servizio durante l'utilizzo dei servizi. Inoltre, l'infrastruttura della cache può essere utilizzata anche dai servizi anziché dalle chiamate dirette al database.
Ashish Gupta,

1
@AshishGupta Esattamente, l'unica differenza nel partizionare i dati su un servizio separato è ciò che l'utente riceve. Invece assemblare il contenuto html + sul server. L'utente riceve dati e html separati e il browser client gestisce il riassemblaggio. Con i dati come servizio separato diventa anche possibile renderli disponibili per applicazioni mobili o altri client non basati sul Web (ad esempio app per smart TV).
Evan Plaice,

13

Per i siti Web che devono essere altamente scalabili come i social network come Facebook, qual è il modo migliore per progettare il sito Web?

Misurare.

Penso che il ...

Cattiva politica.

È richiesta la misurazione effettiva.


Metriche quantitative FTW.
bhagyas,

1
Ok ... quindi cosa succede dopo la misurazione?
Pacerier,

9

La scalabilità non è una funzione di strategie di implementazione specifiche, ma piuttosto di progettare l'architettura dell'applicazione in modo che il livello di accesso ai dati possa evolversi senza un massiccio refactoring e riscrittura.

Un'importante tecnica per costruire un sistema in scala è comprendere i requisiti di accesso ai dati di alto livello e costruire un contratto di interfaccia attorno ad essi. Ad esempio, potresti avere il requisito di ottenere un utente o di elencare le 50 foto pubblicate più di recente da qualsiasi utente .

Non è necessario necessariamente un canale di rete tra la logica aziendale dell'applicazione e la logica di accesso ai dati; una indiretta chiamata metodo con un metodo per operazione logica farebbe bene per iniziare.

Rendere questi metodi di accesso ai dati il ​​più semplici possibile per iniziare. È molto difficile prevedere dove risiederanno i problemi di prestazioni fino a quando l'applicazione non fornisce modelli di utilizzo reali e non si raccolgono dati su dove si verificano colli di bottiglia.

Avendo un'interfaccia di accesso ai dati ben definita è possibile evolvere l'implementazione dell'accesso ai dati senza apportare ampie modifiche all'intera applicazione. Puoi anche decidere di passare a un'architettura di servizio Web in modo trasparente alla tua logica aziendale.

Molte delle risposte di cui sopra forniscono alcuni ottimi consigli su come procedere una volta scoperti i colli di bottiglia delle prestazioni, ma se li applichi troppo presto puoi essere ostacolato dalla complessità del tuo codice prima di sapere se tale complessità è richiesta.


4

Sviluppa un sito Web semplice e lascia che raggiunga un certo livello di traffico. Lungo la linea imparerai come creare siti web scalabili.

Fino a quando non affronti il ​​problema, non puoi pensare alla soluzione .

Fidati di me una volta che hai il sito a rotazione e di fronte al requisito del ridimensionamento, saprai sicuramente come farlo. :-)


Buona citazione !!!!!!!!!!
AmirHossein,

2

È opinione diffusa che le applicazioni Web debbano essere progettate per impostazione predefinita su tre livelli: livelli Web (presentazione), applicazione e database. Questa divisione è dovuta a requisiti diversi per ciascuno dei livelli: in genere accesso / archiviazione su disco di qualità per il database, elevata CPU / memoria a livello di app e elevata larghezza di banda esterna / memoria / dispersione geografica a livello di web. Il livello applicazione / database viene spesso unito in uno fino a molto più tardi nel ciclo di vita dell'applicazione, poiché le macchine di database spesso tendono ad essere server di grandi dimensioni che possono essere costruiti per gestire anche il carico iniziale dell'applicazione.

Il numero specifico di livelli e l'architettura appropriata per la tua applicazione, tuttavia, non devono corrispondere a questo o ad altri modelli.

Pianifica di dover misurare e monitorare tutte le attività nel tuo sistema. Inizia da un design a due o tre livelli e concentrati sulle parti di esso che, come lo stai costruendo, sembrano richiedere la maggior quantità di risorse. Lascia che l'applicazione in esecuzione guidi il tuo design, a questo livello. Maggiore è il numero di informazioni raccolte, più precise e dettagliate sono, migliori sono le decisioni che puoi prendere sulla progettazione dell'applicazione man mano che cresce.

Scegli un framework e un'architettura che, in seguito, ti consentano di ruotare / apportare le modifiche necessarie nel modo più rapido e indolore possibile. Anche se l'accesso ai dati / l'archiviazione / l'elaborazione e l'elaborazione delle applicazioni vengono eseguiti nello stesso eseguibile, se sono correttamente considerati, non sarà così difficile suddividerli in due livelli in un secondo momento, ad esempio.


2

Ogni ulteriore passaggio nella connessione al database è solo un sovraccarico. Ad esempio, tra UI -> Business Facade -> Business -> Data Access -> Databasee UI -> Database, il secondo approccio è più veloce. Tuttavia, più passaggi vengono rimossi, meno il sistema diventa gestibile e maggiore viene la duplicazione. Immagina di scrivere il codice necessario per recuperare l'elenco di amici nel profilo, nella home page, nella pagina di gestione dei demoni, ecc.

Quindi, dovresti trovare un equilibrio tra prestazioni più elevate (che ovviamente influenzano direttamente una maggiore scalabilità) e una migliore manutenibilità .

Tuttavia, non limitarti all'argomento della connessione al database quando pensi di creare siti Web altamente scalabili. Considera anche questi elementi:

  1. Scegliere la piattaforma giusta (PHP è più veloce a causa della sua natura di scripting, ma ASP.NET ha bisogno di compilare il file richiesto al volo per elaborarlo e servire qualcosa. Anche node.js è considerato più scalabile, a causa del suo callback- architettura basata )
  2. Utilizzo dell'architettura RESTful anziché del modello di servizio Web (SOA)
  3. Utilizzo di JSON per il trasferimento di dati anziché XML (che comporta il trasferimento di meno byte)
  4. Seguendo le linee guida sulle prestazioni di Yahoo
  5. Argomenti di rete e hardware come bilanciamento del carico o architettura di livello

2
Non si può dire che PHP sia più veloce. In molti casi, le applicazioni ASP.NET scritte correttamente possono superare le prestazioni di PHP. naspinski.net/post/AspNet-vs-php--speed-comparison.aspx
Andrew Lewis

+1 In realtà, la tua soluzione "semplice" sarà, UI -> Accesso ai dati -> Database. 2 REST è "facile" perché è già integrato nella maggior parte dei browser. Non è necessario ricreare la ruota API comando-risposta. 3 JSON non è solo più piccolo, ma richiede meno passaggi per serializzare-deserializzare perché non è necessario verificare la presenza di entità HTML. Roba buona.
Evan Plaice,

1

Esistono due modi principali per ridimensionare, aumentare e ridurre.

Il ridimensionamento sta sostituendo una macchina con una più potente. Scalare significa aggiungere un'altra macchina per fare il lavoro che stanno facendo le macchine esistenti.

Qualsiasi sito Web ad alto traffico ha bisogno della capacità di ridimensionarsi. L'architettura del software deve essere eseguita in modo tale che più macchine possano essere aggiunte facilmente quanto più il sito diventa occupato.

Di solito questo significa dividere l'applicazione in livelli in modo da poter collegare e riprodurre più server su ogni livello.

Vorrei fare l'opzione 1, avere un servizio invece di farlo direttamente. Finora puoi solo ridimensionare un'applicazione monolitica.


0

Sviluppa il tuo sito utilizzando una piattaforma tecnologica con supporto completamente integrato per il cloud.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.