web-dev-qa-db-fra.com

Quelle est la meilleure façon de concevoir un site Web hautement évolutif?

Pour les sites Web qui doivent être hautement évolutifs, tels que les réseaux sociaux comme Facebook, quelle est la meilleure façon de concevoir le site Web?

  1. Dois-je avoir un service Web dont le site demande pour obtenir les données dont il a besoin?

    ou

  2. Le site devrait-il interroger directement les bases de données? (peut être fait en utilisant des constructions de langage intégrées pour remplir automatiquement les tableaux, etc.).

Je pense que le service Web est la meilleure conception car il donne un accès centralisé aux données et des choses comme la mise en cache et autres deviennent beaucoup plus faciles à contrôler, mais qu'en pensent les autres?

37
Daniel

Wow, c'est une question simple, à laquelle un large éventail de réponses possibles. La partie la plus explicite de votre question demande s'il est plus évolutif de s'interfacer avec votre base de données directement ou via un service Web. Cette réponse est simple: interrogez directement la base de données. Passer par le service Web ajoute un tas de latence qui est complètement inutile pour le code fonctionnant derrière un pare-feu (dans l'ensemble). Un service Web, par exemple, nécessite un composant pour recevoir une demande, la désérialiser, interroger la base de données, sérialiser une réponse et la renvoyer. Donc, si votre code fonctionne tous derrière un pare-feu, épargnez-vous la peine et interrogez directement la base de données.

Rendre un site Web évolutif va cependant bien au-delà de la question que vous avez initialement posée. Alors pardonnez-moi si je pars sur une tangente ici, mais j'ai pensé que cela pourrait être utile étant donné que vous avez mentionné Facebook en particulier.

Je vous recommanderais de lire le travail et les outils construits par Brad Fitzpatrick (fondateur de LiveJournal et maintenant chez Google). Lorsque j'ai travaillé avec lui à Six Apart, voici quelques-unes des choses que j'ai apprises de lui, et sur l'architecture de LiveJournal qui l'a rendue si évolutive.

  1. tilisez des tables de base de données étroites plutôt que des tables larges. Ce qui était fascinant à ce sujet, c'était d'apprendre ce qui a motivé cette architecture, qui créait un système facilement et rapidement mis à niveau. Si vous utilisez des tables larges ou des tables pour lesquelles chaque champ ou propriété est une colonne de la table, lorsque vient le temps de mettre à niveau le schéma de base de données, par exemple en ajoutant une nouvelle colonne, le système devra verrouiller la table pendant que le schéma le changement est mis en œuvre. Lors d'un fonctionnement à grande échelle, cela signifierait qu'une simple modification du schéma de la base de données pourrait entraîner une panne importante de la base de données. Ce qui craint évidemment. En revanche, une table étroite stocke simplement chaque propriété individuelle associée à un objet sous la forme d'une seule ligne dans la base de données. Par conséquent, lorsque vous souhaitez ajouter une nouvelle colonne à la base de données, il vous suffit d'insérer des enregistrements dans une table, ce qui est une opération non verrouillable. Ok, c'est un peu de fond, voyons comment ce modèle se traduit réellement dans un système de travail comme LiveJournal.

    Supposons que vous souhaitiez charger les 10 dernières entrées de journal sur le blog d'une personne, et supposons que chaque entrée de journal possède dix propriétés. Dans une disposition de table large classique, chaque propriété correspondrait à une colonne d'une table. Un utilisateur interrogerait alors la table une fois pour récupérer toutes les données dont il a besoin. La requête retournerait 10 lignes et chaque ligne aurait toutes les données dont elles ont besoin (par exemple SELECT * FROM entrées ORDER BY date LIMIT 10). Dans une disposition de table étroite, les choses sont cependant un peu différentes. Dans cet exemple, il y a en fait deux tables: la première table (table A) stocke des critères simples sur lesquels vous souhaitez rechercher, par ex. l'id de l'entrée, l'id de l'auteur, la date de l'entrée, etc. Une deuxième table (table B) stocke alors toutes les propriétés associées à une entrée. Cette deuxième table comprend trois colonnes: entry_id, key et value. Pour chaque ligne du tableau A, il y aurait 10 lignes dans le tableau B (une ligne pour chaque propriété). Par conséquent, pour récupérer et afficher les dix dernières entrées, vous auriez besoin de 11 requêtes. La première requête vous donne la liste des ID d'entrée, puis les dix requêtes suivantes récupèrent les propriétés associées à chacune des entrées renvoyées dans la première requête.

    "Holy moly!" vous dites: "Comment diable cela peut-il être plus évolutif?!" Son droit totalement contre-intuitif? Dans le premier scénario, nous n'avions qu'une seule requête de base de données, mais dans la deuxième solution "plus évolutive", nous avons 11 requêtes de base de données. Ça n'a aucun sens. La réponse à cette question repose entièrement sur la puce suivante.

  2. tilisez memcache généreusement. Au cas où vous ne seriez pas au courant, memcache est un système de mise en cache basé sur le réseau distribué, sans état et à faible latence. Il est utilisé par Facebook, Google, Yahoo et à peu près tous les sites Web populaires et évolutifs de la planète. Il a été inventé par Brad Fitzpatrick en partie pour aider à compenser la surcharge de base de données inhérente à une conception de base de données de table étroite. Jetons un coup d'œil au même exemple que celui discuté au n ° 1 ci-dessus, mais cette fois, introduisons memcache.

    Commençons quand un utilisateur visite une page pour la première fois et qu'il n'y a rien dans le cache. Vous commencez par interroger la table A qui renvoie les ID des 10 entrées que vous souhaitez afficher sur la page. Pour chacune de ces entrées, vous interrogez ensuite la base de données pour récupérer les propriétés associées à cette entrée, puis l'utilisation de ces propriétés constitue un objet avec lequel votre code peut s'interfacer (par exemple, un objet). Vous stockez ensuite cet objet (ou une forme sérialisée de cet objet) dans memcache.

    La deuxième fois que quelqu'un charge la même page, vous commencez de la même manière: en interrogeant le tableau A pour la liste des ID d'entrée que vous afficherez. Pour chaque entrée, vous allez d'abord dans memcache et vous dites: "avez-vous l'entrée #X dans le cache?" Si oui, alors memcache vous renvoie l'objet d'entrée. Sinon, vous devez à nouveau interroger la base de données pour récupérer ses propriétés, constituer l'objet et le ranger dans memcache. La plupart du temps, la deuxième fois que quelqu'un visite la même page, il n'y a qu'une seule requête de base de données, toutes les autres données sont ensuite extraites directement de memcache.

    Dans la pratique, ce qui s'est finalement produit pour la plupart de LiveJournal est que la plupart des données du système, en particulier les données les moins volatiles, ont été mises en cache dans memcache et les requêtes supplémentaires à la base de données nécessaires pour prendre en charge le schéma de table étroite ont été presque complètement compensées.

    Cette conception a facilité la résolution du problème associé à l'assemblage d'une liste de messages associés à tous vos amis dans un flux, ou "mur", beaucoup beaucoup plus facile.

  3. Ensuite, envisagez de partitionner votre base de données. Le modèle discuté ci-dessus fait apparaître un autre problème, et c'est que vos tables étroites auront tendance à être très grandes/longues. Et plus il y a de lignes, plus les autres tâches administratives deviennent difficiles. Pour compenser cela, il peut être judicieux de gérer la taille de vos tables en partitionnant les tables d'une manière ou d'une autre, afin que les clusters d'utilisateurs soient servis par une base de données et qu'un autre cluster d'utilisateurs soit desservi par une base de données distincte. Cela répartit la charge sur la base de données et maintient les requêtes efficaces.

  4. Enfin, vous avez besoin d'index impressionnants. La vitesse de vos requêtes dépendra en grande partie de la qualité de l'indexation des tables de votre base de données. Je ne passerai pas trop de temps à discuter de ce qu'est un index, sauf pour dire que cela ressemble beaucoup à un système de catalogue de cartes géant pour rendre plus efficace la recherche d'aiguilles dans une botte de foin. Si vous utilisez mysql, je vous recommande d'activer le journal des requêtes lentes pour surveiller les requêtes qui prennent beaucoup de temps à répondre. Lorsqu'une requête apparaît sur votre radar (par exemple parce qu'elle est lente), déterminez ensuite quel index vous devez ajouter au tableau pour l'accélérer.

"Merci pour tout ce beau fond, mais sacré crud, c'est beaucoup de code que je vais devoir écrire."

Pas nécessairement. De nombreuses bibliothèques ont été écrites qui facilitent vraiment l'interfaçage avec memcache. D'autres bibliothèques encore ont codifié l'ensemble du processus décrit ci-dessus; Data :: ObjectDriver en Perl est exactement une telle bibliothèque. Comme pour les autres langues, vous devrez faire vos propres recherches.

J'espère que vous avez trouvé cette réponse utile. Ce que j'ai constaté le plus souvent, c'est que l'évolutivité d'un système se résume souvent de moins en moins au code, et de plus en plus à une stratégie de stockage et de gestion/conception technique solide.

41
Byrne Reese

Pour les sites Web qui doivent être hautement évolutifs tels que les réseaux sociaux comme Facebook, quelle est la meilleure façon de concevoir le site Web?

Mesure.

Je pense que le ...

Mauvaise politique.

Une mesure réelle est requise.

13
S.Lott

L'évolutivité n'est pas fonction de stratégies d'implémentation spécifiques, mais plutôt de la conception de l'architecture de votre application afin que la couche d'accès aux données puisse évoluer sans refactorisation et réécriture massives.

Une technique importante dans la construction d'un système évolutif consiste à comprendre vos besoins d'accès aux données de haut niveau et à construire un contrat d'interface autour d'eux. Par exemple, vous devrez peut-être obtenir un utilisateur ou répertorier les 50 photos publiées le plus récemment par un utilisateur.

Vous n'avez pas nécessairement besoin d'un canal réseau entre la logique métier de votre application et la logique d'accès aux données; une indirection d'appel de méthode avec une méthode par opération logique ferait bien de démarrer.

Rendez ces méthodes d'accès aux données aussi simples que possible pour commencer. Il est très difficile de prévoir où se situeront les problèmes de performances tant que votre application ne servira pas de modèles d'utilisation réels et que vous ne collecterez pas de données sur les points où vous avez des goulots d'étranglement.

En ayant une interface d'accès aux données bien définie, vous pouvez faire évoluer votre implémentation d'accès aux données sans apporter de modifications importantes à l'ensemble de votre application. Vous pouvez également décider de passer à une architecture de service Web de manière transparente à votre logique métier.

La plupart des réponses ci-dessus donnent d'excellents conseils sur la façon de procéder une fois que vous avez découvert vos goulots d'étranglement en matière de performances, mais si vous les appliquez trop tôt, vous pouvez être paralysé par la complexité de votre code avant de savoir si cette complexité est même requise.

9
Martin Atkins

Développez un site Web simple et laissez-le atteindre un certain niveau de trafic. Dans le même esprit, vous apprendrez à créer des sites Web évolutifs.

Jusqu'à ce que vous rencontriez le problème, vous ne pouvez pas penser à une solution.

Faites-moi confiance une fois que le site évolue et fait face à l'exigence de mise à l'échelle, vous saurez certainement comment le faire. :-)

4
Pankaj Upadhyay

Il est généralement admis que les applications Web doivent être conçues avec trois niveaux par défaut: couches Web (présentation), application et base de données. Cette division est due à des exigences différentes à chacune des couches - généralement un accès/stockage de disque de qualité pour la base de données, un processeur/mémoire élevé au niveau de la couche d'application et une bande passante externe/mémoire/dispersion géographique élevée au niveau de la couche Web. La couche application/base de données est souvent fusionnée en une seule jusqu'à bien plus tard dans le cycle de vie de l'application, car les machines de base de données ont souvent tendance à être des serveurs massifs qui peuvent également être construits pour gérer la charge d'application précoce.

Le nombre spécifique de couches et l'architecture appropriée pour votre application, cependant, ne doivent pas nécessairement correspondre à ce modèle ou à tout autre modèle.

Prévoyez de mesurer et de surveiller toutes les activités de votre système. Commencez par une conception à deux ou trois niveaux et concentrez-vous sur les parties qui, au fur et à mesure que vous la construisez, nécessitent le plus de ressources. Laissez l'application en cours guider votre conception à ce niveau. Plus vous collectez d'informations, et plus elles sont précises et détaillées, meilleures sont les décisions que vous pouvez prendre pour concevoir l'application à mesure qu'elle grandit.

Choisissez un cadre et une architecture qui, plus tard, vous permettront de faire pivoter/apporter les modifications requises aussi rapidement et sans douleur que possible. Même si votre accès aux données/stockage/traitement et le traitement des applications sont effectués dans le même exécutable, s'ils sont correctement factorisés, il ne sera pas aussi difficile de les diviser en deux couches plus tard, par exemple.

2
blueberryfields

Toute étape supplémentaire de connexion à la base de données n'est qu'une surcharge. Par exemple, entre UI -> Business Facade -> Business -> Data Access -> Database et UI -> Database, la deuxième approche est plus rapide. Cependant, plus vous supprimez d'étapes, moins votre système est maintenable et plus il y a de duplication. Imaginez écrire le code nécessaire pour récupérer la liste d'amis dans le profil, la page d'accueil, la page de gestion des démons, etc.

Donc, vous devriez faire un équilibre ici entre des performances plus élevées (ce qui affecte bien sûr directement une plus grande évolutivité) et une meilleure maintenabilité .

Mais ne vous limitez pas à le sujet de connexion à la base de données lorsque vous pensez à créer des sites Web hautement évolutifs. Tenez également compte de ces éléments:

  1. Choisir la bonne plate-forme (PHP est plus rapide en raison de sa nature de script, mais ASP.NET doit compiler le fichier demandé à la volée pour le traiter et servir quelque chose. Aussi node.js est censé être plus évolutif, en raison de son architecture basée sur le rappel )
  2. Utilisation d'une architecture RESTful au lieu d'un modèle de service Web (SOA)
  3. Utilisation de JSON pour le transfert de données au lieu de XML (ce qui se traduit par moins d'octets à transférer)
  4. Suivre Yahoo directives de performance
  5. Rubriques réseau et matériel comme équilibrage de charge , ou architecture de niveau
2
Saeed Neamati

Il existe deux façons principales d'évoluer, de monter et de descendre.

La mise à l'échelle, c'est remplacer une machine par une plus puissante. La mise à l'échelle signifie ajouter une autre machine pour effectuer le travail que font les machines existantes.

Tout site Web à fort trafic doit pouvoir évoluer. L'architecture logicielle doit être effectuée de manière à ce que plus de machines puissent être ajoutées facilement plus le site est occupé.

Habituellement, cela signifie diviser l'application en niveaux afin de pouvoir brancher et jouer plus de serveurs à chaque niveau.

Je ferais l'option 1, avoir un service au lieu de le faire directement. Jusqu'à présent, vous ne pouvez mettre à l'échelle qu'une application monolithique.

1
Jon Raynor

Développez votre site à l'aide d'une plate-forme technologique qui prend totalement en charge le cloud.

0
bhagyas