juillet
2009
Salut
Excellent et surprenant article d’infoq sur les meilleures pratiques ebay pour supporter une charge qu’on devine conséquente…
L’article présente 7 bonnes pratiques, en voici une rapide traduction, plus de détails (en anglais) sur l’article en question.
Cela donne :
1 : découper par fonctionnalité : plus les fonctionnalités sont découplées les unes des autres, meilleur c’est ! Au niveau du code, privilégier des jar distincts les uns des autres. Au niveau des serveurs d’applications, faire des « pools » par fonctionnalité. Il en va de même pour les bases de données, en faire par fonctionnalité -> base pour les users, base pour les objets et ainsi de suite. L’idée est de pouvoir booster une fonctionnalité en particulier en cas de grosse consommation de charge.
2 : découper horizontalement : au sein même d’une fonctionnalité, toujours découpler : privilégier donc une application « stateless » afin qu’une demande puisse être servie par n’importe quelle machine derrière un load balancer. Pour les données, c’est pareil, par exemple pour les utilisateurs, y associer x hosts avec une règle de répartition simple -> du coup accroître la capacité est simple.
3 : éviter les transactions distribuées : on connaît tous les transactions, elles sont d’ailleurs très souvent citées comme une bonne pratique par excellence. Or rien de plus coûteux en environnement distribué… De plus, la théorie CAP dit que parmi les 3 qualités recherchées pour un système distribué consistency (C) – validité des données, availability (A) – disponibilité, et partition-tolerance (P) – partitionnement, seuls 2 sont possibles à la fois. Or la disponibilité et le partitionnement sont des contraintes fondamentales pour un site web à forte audience tournant 24h/24. Aussi la plupart des transactions chez ebay sont autocommitées, seules celles sur une unique base sont parfois transactionnelles de bout en bout.
4 : privilégier l’asynchrone : en synchrone, augmenter la vitesse de réponse d’une demande passe par une augmentation de tous les éléments impliqués dans la chaîne, si A supporte 10 fois plus de requêtes, B devra faire pareil.
5 : traiter les flux de manière asynchrone : dans un flux synchrone, vous devez pouvoir supporter les piques de charge à la seconde près. En asynchrone, vous pouvez vous contenter de traiter la demande moyenne, les piles s’occupant de gérer les piques de charge.
6 : virtualiser à tous les niveaux : suivez le vieil adage d’informaticien que la solution à tous les problèmes est d’ajouter un niveau d’abstraction. L’OS sépare du matériel, La machine virtuelle sépare de l’OS, la couche DAO sépare de la base de données, les répartiteurs de charge et les IPs virtuelles rendent abstraits le réseau et ainsi de suite. Ainsi, en plus d’être plus simple pour le développeur, on a une flexibilité opérationnelle : si un système logiciel ou matériel plante, les requêtes peuvent être reroutées. De plus, avec assez de niveau d’abstraction, les plus hautes couches peuvent aller jusqu’à ignorer ses problèmes.
7 : user du cache avec pertinence : il y a là moins de règles générale, plus on affecte de la mémoire pour cacher des données, moins on en a pour traiter les demandes entrantes. Fais de bonne façon, on peut alors avoir un système qui monte en charge de façon moindre que linéaire : les demandes suivantes récupèrent les données du cache et n’ont plus besoin d’aller à la BDD. Au final, il faut s’assurer que le cache soit approprié à la situation. L’auteur de l’article dit d’ailleurs n’avoir encore jamais vu de système où cacher les données n’était pas approprié d’une certaine manière.
En conclusion, la montée en charge doit se prévoir initialement, et non à posteriori, tant cela est structurant pour une application.
J’espère que cela vous a plus, l’article est assurément bien mieux
++
Joseph
On fait exactement comme eux sur developpez.com