Liens connexes

Dépêche modérée par

Dépêche éditée par

: Répartition de charge : axes de réflexion et quelques exemples de solutions libres

Posté par yannig (page perso, ). Modéré le 18 juin 2009.
31
Il vous est sans doute arrivé de ne plus être en mesure de faire face aux nombres de transactions d’une application, d’avoir des impératifs de résultat vis-à-vis des pannes matérielles (réduire votre temps d'indisponibilité), de vouloir améliorer les performances de votre système ou d’en augmenter les capacités.
Nous avons souvent vu, chez des clients victimes de leur succès, une application devant faire face à des centaines de transactions par seconde alors qu’elle était prévue pour une dizaine seulement.
Dans ce cas, on améliore le système par l’adjonction de nouveaux éléments qui permettent d’augmenter sa capacité transactionnelle. Il existe également des techniques de basculement dans le cas de crash. Dans ce cas, on ne fait que des reprises automatiques d’activité sans faire appel à de la répartition de charge.

Cette solution est intéressante lorsqu’un nœud supporte le volume de transaction et que l’ajout d’un répartiteur de charge fait augmenter la charge du système.
Dans ce qui va suivre, j'essaierai de vous présenter quelques solutions applicables à différentes parties d'une chaîne applicative n-tiers classique.

> Lire la suite (36 commentaires, moyenne: 3,9).   [dépêche : 16647 caractères]

Quels sont les principes de répartition de charge ?

Il n’existe pas beaucoup de familles de solution. On n'a globalement que deux techniques :
Ces méthodes ont leurs avantages et leurs inconvénients. Le gestionnaire de pool augmentera la complexité mais apportera plus de souplesse et de sûreté vis-à-vis des pannes. La solution à base de round-robin DNS ou applicatif sera plus simple mais entraînera une complexification de la chaîne applicative.

Néanmoins certains produits permettent de gérer cette répartition de charge en interne, comme par exemple Tomcat, JBoss ou MySQL. Pour ce dernier, on doit installer un proxy.

Certains serveurs d’applications Java permettent de gérer une répartition de charge à leur niveau. Par exemple, multi-pool JDBC pour les connexions aux bases de données ou gestion des grappes de serveurs via l'utilisation de pilotes JDBC.

Quels produits peuvent en bénéficier ?

Plusieurs grandes familles de produit peuvent profiter des solutions de répartition de charge. Chez simia, nous sommes intervenus sur des bases de données, serveurs Web, serveurs Java/J2EE...

Certaines techniques sont très simples, comme l’ajout d’un répartiteur de charge au niveau TCP. D’autres réclament des connaissances très fines du produit, voire de l’application. Par exemple, le découpage au sein d’une application des requêtes en base entre lecture et écriture.

L’impact budgétaire ne sera donc pas le même selon le type de produit. Attention également à bien évaluer les ressources nécessaires.

Nous recommandons de qualifier où se trouve la contention dans la chaîne applicative n-tiers et de privilégier les solutions simples. Il est inutile d’optimiser certaines chaînes très performantes, comme un serveur web de page statique, alors que la contention se trouve au niveau d’une base surchargée.

Paradoxalement, les produits les plus performants s’intègrent généralement très facilement au sein d’une boucle de répartition de charge. On le constate pour les serveurs Web/Java/J2EE. Alors que d’autres seront plus difficiles à intégrer comme les bases de données.

Serveur Web

Le serveur Web reste de loin l’élément le plus simple à mettre au sein d’une boucle de charge. En dehors de quelques problématiques de sessions, vous n’aurez pas à vous soucier de la réplication et de la fraîcheur de vos données comme vous auriez à le faire sur une base de données, par exemple.

HAProxy

Ce produit, beaucoup moins connu qu’Apache, répond scrupuleusement à la philosophie Unixienne. C’est-à-dire « un outil par besoin ». Son fonctionnement est très simple. Vous le positionnez en frontal des produits que vous avez à mettre dans votre boucle de répartition de charge. Vous renseignez un fichier de configuration. Vous lancez le process. Votre boucle de répartition de charge est en place !

Vous pourrez facilement faire une répartition de charge sur n’importe quel type de protocole TCP. La documentation est bien faite avec de nombreux exemples qui vous permettront de le déployer facilement dans votre infrastructure. De plus, depuis la version 1.3, il est possible de gérer une redirection en fonction du contenu de la requête au niveau HTTP (page dynamique vs statique) et de bloquer les requêtes en fonction de leur contenu. Une description complète des fonctionnalités du produit est disponible sur leur site Web [HAPROXY]

Enfin, ce produit met à disposition des binaires pour les Unix Solaris (Sparc et Intel) ou Linux (Intel et AMD64).

Greffons Apache/J2EE

L’utilisation d’un serveur d’application n’implique pas forcément une notion de répartition de charge. Néanmoins on peut faire appel à des greffons Apache qui s’y prêtent très bien.

Les avantages sont multiples :
Pour le clustering des sessions, Tomcat ou JBoss offrent ce type de service. Certains serveurs d’application propriétaire comme WebLogic ou WebSphere également (à un prix conséquent). Toutefois, ils ont l’inconvénient d’augmenter la charge processeur ainsi que la communication réseau entre les serveurs J2EE de votre grappe. Plus vous augmentez le nombre d’éléments dans votre boucle de charge, plus vous augmentez le poids de cette surcharge processeur et réseau de manière exponentielle. Il est donc important de qualifier sérieusement vos besoins par des benchmarks afin de valider une solution. Il est également important de savoir si la notion de grappe de serveurs est essentielle ou non à votre système d’informations.

Vous pouvez par exemple découper votre application en fonction de la criticité de ses différentes parties. La consultation est moins critique en qualité de service mais plus gourmande en ressources. Un formulaire de paiement réclame une quantité de transaction moins élevée mais avec une qualité de service beaucoup plus exigeante.

Une répartition de charge à l’aide de greffon J2EE pour Apache implique de séparer le contenu statique d’un site Web (feuille de style, images, pages HTML statiques) de la partie dynamique. Une réorganisation du contenu de vos applications sera très utile.

Reverse proxy

Le Reverse Proxy permet d’envoyer vos requêtes – via un algorithme de répartition de charge – aux différents nœuds d’une boucle de répartition de charge. Outre cette répartition de charge, il peut aussi procéder aux opérations suivantes :
Avec le reverse proxy sur un greffon J2EE, vous n’aurez pas à vous soucier de l’organisation de votre application (séparation du contenu statique du contenu dynamique). En revanche, vous ne pourrez pas bénéficier des mêmes possibilités en termes de gestion de persistance des sessions au sein d’une grappe que peut offrir un greffon J2EE. Rien ne vous empêche de combiner les deux solutions.

Base de données

Les bases de données comme MySQL et PostgreSQL, les deux références incontournables du marché, sont de grands centres de consommation de ressources. Chacune ont des solutions de répartitions de charge, fiables et reconnues.

Avant tout, il convient de qualifier le ratio lecture/écriture lors de la mise en place d’une répartition de charge sur ce type de produit. Ces solution se comportent beaucoup mieux dans le cas d’un fort ratio en faveur des lectures.

Remarque : dans le cas d’un ratio en lecture à 100%, il est tout à fait imaginable de procéder à la mise à jour des données par un autre moyen. Rien n’empêche par exemple d’utiliser un moyen classique d'export/import ou batch de mise à jour sur chaque nœud.

Regardons pour MySQL et PostgreSQL les réplications maître/esclave de vos données – étape essentielle pour garantir la mise en place d’une répartition de charge sur plusieurs nœuds – et la répartition des lectures sur plusieurs bases.

Répartition de charge et réplication avec MySQL

Cette fonctionnalité fait partie intégrante de MySQL. Elle est très souple en termes de fonctionnement. Le principe est assez simple : vous définissez un nœud comme étant le maître et vous lui rattachez un ou plusieurs esclaves. Le produit prendra en compte les modifications au fil de l’eau et gardera les requêtes en attente dans le cas d’une interruption de service. Petit raffinement intéressant, il est possible de croiser les réplications et donc de faire des réplications maître/maître. Cette partie ayant été souvent documentée, je vous propose de vous reporter aux articles dans la section bibliographie [MYSQL].

Autres fonctionnalités intéressantes : le filtrage des bases à reproduire. En effet, votre application peut avoir besoin d’un emplacement temporaire de stockage pour des données de sessions, un contenu de caddie etc. Alors, il est possible de ne répliquer qu’une seule partie de vos schémas de données. Cela réduit d’autant le besoin de resynchronisation entre vos différents nœuds. Bien sûr, si vos sessions ne doivent pas perdre d’information, vous devez répliquer toutes les données.

La réplication en place, il reste à mettre en œuvre mysql-proxy. Il suffit de donner en paramètre la liste de vos serveurs MySQL, le port d’écoute de votre proxy et de changer l’adresse/port de votre base. Vous pointez ainsi sur votre proxy et disposez d’une répartition de charge automatique. Une limitation à cet outil : il ne sait pas – pour l’instant – faire de séparation au niveau des requêtes en lecture/écriture. On doit donc gérer la gestion des adresses en lecture et en écriture au niveau de l’application.

Pour de plus ample détail, vous pouvez vous reporter aux articles sur le proxy de MySQL proposés en bibliographie [Proxy-MySQL].

Avant propos sur les solutions avec PostgreSQL

Contrairement à MySQL, PostgreSQL ne dispose pas directement de solution de réplication. On doit faire appel à un produit Tiers comme SLONY ou PGPOOL.

PostgreSQL Slony-I

Le principe pour Slony est simple. Vous donnez le nom d’une base à répliquer, le nom des bases dans lesquels vous devez recopier et enfin le nom des serveurs correspondants.

Cette solution présente des limitations à plusieurs niveaux :
Le problème de non temporisation des écritures peut être considéré comme secondaire dans la mesure où en cas de crash d'une machine, la reprise se fait rarement sans intervention. D'autre part, en cas de crash sur MySQL, des fichiers sont créés sur la machine maître. Si le service est trop long à se rétablir avec une activité transactionnelle soutenue, vous pourrez saturer vos disques !

Enfin, on est dans l’obligation d’ajouter un produit permettant de faire un proxy des requêtes [PL/Proxy] ou de gérer au niveau de l’application.

PostgreSQL pgpool-II

Là encore, sa mise en place se révèle assez simple pour la répartition de lectures et écritures sur plusieurs nœuds.

Il est aussi capable de gérer des partitions (répartition des tables en fonction de règles). Un exemple simple de ce type d'application est de répartir une table sur plusieurs nœuds en utilisant, par exemple, la parité ou le résultat d'une division entière sur une clé primaire de type entier. On découpe ainsi la volumétrie et la charge entre les différentes machines de la boucle de charge.

Comme toujours, de nombreux tutoriels existent (voir la bibliographie de l'article [PGPOOL]).

En résumé, pgpool est plus riche en terme de fonctionnalités. On peut noter les points forts suivants :
Serveur d'application Java et Pilotes proxy JDBC

Les proxys JDBC, outils de clustering de base de données, sont complètement génériques. Ils fonctionneront pour toutes les bases de données du marché possédant un pilote JDBC. Leur principal défaut est de ne fonctionner que pour les serveurs Java/J2EE.

Le principe est simple, ils se substituent au pilote Java utilisé pour gérer habituellement les connexions à votre base. On précise ensuite en paramètre le nom de l'ancien pilote sur lequel on va s’appuyer pour se connecter réellement à la base. Il existe quelques références comme [SEQUOIA], [C-JDBC] ou [HA-JDBC], l'avantage de ces outils étant de supprimer le besoin de disposer d'un élément servant de proxy.

Comme toujours, lors de l'adoption d'une de ces solutions, il vous faut qualifier l'impact sur les performances sur le système informatique en réalisant un benchmark.

Avant d’aller plus loin

Les solutions sont très nombreuses ? C’est pourquoi, avant d’en adopter une, il est important de qualifier les impacts lors de l'ajout de ces composants et de gérer le risque. Rien ne doit être entrepris au détriment des performances.

Bibliographie

[HAPROXY] fonctionnalités du HAProxy : http://haproxy.1wt.eu/#desc

[MYSQL] Réplication master/master MySQL : http://www.howtoforge.com/mysql_master_master_replication

[MySQL-Proxy]
Réplication master/master MySQL : http://www.oreillynet.com/pub/a/databases/2007/07/12/getting(...)
Manuel d'utilisation du proxy MySQL : http://dev.mysql.com/doc/refman/6.0/en/mysql-proxy-using.htm(...)

[SLONY] Réplication master/slave PostgreSQL/Slony http://www.linuxjournal.com/article/7834

[PL/Proxy] Tutoriel d'utilisation de PL/Proxy : http://plproxy.projects.postgresql.org/doc/tutorial.html

[PGPOOL] Répartition de charge avec pgpool : http://pgpool.projects.postgresql.org/pgpool-II/doc/tutorial(...)

[SEQUOIA] Sequoia solution transparente de clustering : http://www.continuent.com/community/tungsten-connector

[C-JDBC] Ancêtre de Sequoia : http://c-jdbc.ow2.org/

[HA-JDBC] Proxy léger et transparent pour JDBC : http://ha-jdbc.sourceforge.net/

Cette discussion est archivée, il n'est plus possible de laisser des commentaires.

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.

RDBMS sucks

Posté par Nÿco (Jabber id, page perso, ) le 18/06/2009 à 23:18. (lien). Évalué à 7.

Si c'est la cadence des transactions qui pose problème, il n'est peut-être pas la peine de déployer un gigantesque usine à gaz, mais plutôt changer de type de base de données ? En l'occurrence, le modèle relationnel a vécu, il est grand temps de passer à autre chose dans un bon nombre de cas :
http://couchdb.apache.org/
http://www.erlang.org/doc/apps/mnesia/
http://jackrabbit.apache.org/
http://www.mongodb.org/
http://incubator.apache.org/cassandra/
...ne sont que quelques exemples...

--
Jabber ID : xmpp:Nyco@jabber.fr

Comment ne rien améliorer

Posté par ǝsɐʃdoıx∀ ıɥs∀ (page perso, ) le 19/06/2009 à 06:39. (lien). Évalué à 2.

Bon, avant toute chose je ne dénigre pas du tout le projet, hein !

Nous avons souvent vu, chez des clients victimes de leur succès, une application devant faire face à des centaines de transactions par seconde alors qu’elle était prévue pour une dizaine seulement. Dans ce cas, on améliore le système par l’adjonction de nouveaux éléments qui permettent d’augmenter sa capacité transactionnelle.

J'aurais tendance à dire "dans ce cas, on vire le chef de projet et l'architecte logiciel, et on engage des gens qui font faire à leurs programmeurs un logiciel robuste dès de départ. Et si ça suffit pas, on rachète de la ram."

On fait pas un logiciel "pour une dizaine de transactions". On fait pour une seule, ou pour un nombre arbitrairement grand. La conception c'est un art et un métier. (Il faut réglementer l'industrie logicielle, définir des responsables pénaux en cas de bug, légiférer l'obtention ou la perte d'un titre de programmeur, architecte, chef de projet, bla, bla, etc)

--
Je ne suis pas toujours de mon avis.

PostgreSQL master/master

Posté par Laurent Cligny (page perso, ) le 19/06/2009 à 08:17. (lien). Évalué à 5.

Pour la réplication synchrone master/master et la répartition de charge de postgresql il y a cybercluster:

http://www.postgresql.at/english/pr_cybercluster_e.html

Il s'agit d'un PostgreSQL 8.3 modifié pour supporter ce type de réplication. La licence est toujours la BSD.

Test de montée en charge

Posté par passant () le 19/06/2009 à 09:53. (lien). Évalué à 8.

Pour les personnes qui veulent savoir si leur application tiendra la charge, je leur conseille d'utiliser des programmes tels que :

- OpenSTA - libre et gratuit
- Mercury LoadRunner - $$$$
- JMeter - libre et gratuit

Le fonctionnement est assez simple. imaginez que vous avez un magasin en ligne. Il y a un certains nombre d'étapes à respecter pour qu'une transaction soit terminée

- page d'accueil
- choisir un ou plusieurs produits : visiter le site
- S'identifier ou créer un compte
- Confirmer la commande
- Effectuer le paiement
- Page de confirmation de paiement
- Logout : des fois, des fois non

Sur chacune de ces étapes vous installer un timer. Ensuite, vous demandez à votre programme de simuler de quelques dizaines à plusieurs centaines d'utilisateur. Vous pouvez également, du côté des serveurs, installer des suivis de consommation processeur, memoire, disque dur, etc...

ET voilà. Une fois terminé vous pourrez-voir comment se comporte les durée de transaction en fonction du nombre de user et les ressources que cela consomme. Ce genre de teste permet de rapidement savoir ce qui pose problème. Par expérience, les problème qui arrivaient le plus souvent étaient un serveur de base de donnée sous dimensionné et une surutilisation des lock pour certaines opérations.

my 2cents

--
--

Réplication Mysql master/master

Posté par Sébastien PAUSET () le 19/06/2009 à 09:59. (lien). Évalué à 5.

Bonjour,

Attention, la réplication mysql master/master existe et est possible, mais avec certaines limitations : en particulier il n'y a pas de garantie de temps de réplication, elle est asynchrone. de plus il n'y a pas de gestion des conflits.

exemple de cas problématique :
j'insère une donnée avec auto incrément à gauche.

ma réplication a du retard. avant que ma donnée soit répliquée, une autre donnée est insérée à droite sur la même table. quand je rattrape mon retard, ma première donnée venant de gauche s'insère à droite. sauf que son id primaire est déjà pris par ma donnée insérée à droite --> conflit.

donc globalement la réplication master/master est possible, mais avec des limitations dont il faut tenir compte dans le développement de son appli.

--
-- Seb

Et les SSI ?

Posté par Jean Parpaillon (Jabber id, page perso, ) le 19/06/2009 à 12:06. (lien). Évalué à 2.

Parmi les solutions de répartition de charge, on peut citer également des solutions génériques de type SSI: OpenSSI, Mosix, Kerrighed [1]. À ma connaissance, actuellement, seul Kerrighed est activement maintenu.

Pour rappel, ces solutions créent un SMP virtuel en aggrégeant les CPUs des noeuds d'une grappe. L'avantage est que ces solutions (au niveau noyau) ne demandent aucune configuration spéciale des applications. Vous pouvez augmenter le nombre de processeurs au fur et à mesure des besoins.

[1] http://kerrighed.org/

et les annuaires ?

Posté par mortimer () le 19/06/2009 à 12:08. (lien). Évalué à 5.

J'aurais bien vu un paragraphe sur les annuaires ldap dans cette dépêche.

La gestion du failover sur les annuaires ldap est prévue dans le protocole, puisqu'il est possible de spécifier plusieurs serveurs lors d'une connexion. Un client respectueux des textes essaiera de lui-même successivement les différents serveurs en cas d'échec de connexion.

Pour ce qui est de la répartition de charge, les solutions sont multiples : referrals (découpage de l'arbre en sous branches servies par des serveurs différents), reverse proxy avec plusieurs annuaires derrière, etc.

La réplication des données d'un annuaire ldap n'est pas éloignée du cas des sgbd. D'ailleurs, avec openldap, il est possible d'utiliser un mysql par exemple comme backend de stockage des données (voir http://www.mysql.com/news-and-events/web-seminars/display-36(...) à ce propos). Dans le cas le plus courant, il s'agit de bases Berkeley, et la réplication est faite au niveau ldap (avec ici encore plusieurs solutions et plusieurs configurations possibles). Des produits comme l'annuaire de Sun, ou de Redhat/Fedora (même racine que Sun) communiquent sur leur capacité à monter des configurations à 4 serveurs avec deux maîtres (donc réplication mutlimaître entre eux) et chacun un esclave (http://www.redhat.com/docs/manuals/dir-server/ag/8.0/Managin(...) voire 4 maîtres et n esclaves (http://www.redhat.com/docs/manuals/dir-server/ag/8.0/Managin(...) Openldap, après avoir longtemps refusé d'officialiser le support de la réplication multimaître (c'était un fonctionnalité non documentée pendant un moment, mais les développeurs ont toujours pensé que ce genre de conf apportait plus de risques que d'avantages, et qu'il était rarement impossible de s'en passer http://www.openldap.org/cgi-bin/wilma_hiliter/openldap-softw(...) http://www.openldap.org/lists/openldap-software/200206/msg00(...) a fini par l'intégrer officiellement dans la version 2.4 (http://en.wikipedia.org/wiki/OpenLDAP#Release_summary).

Enfin voilà, quoi.

Ça tombe bien

Posté par MCMic (page perso, ) le 19/06/2009 à 17:23. (lien). Évalué à 5.

J'ai aussi un journal de prévu sur la réplication de BDD.
Par contre le mien causera plus de la réplication multi-maître (éventuellement asynchrône).

J'ai prévu d'y présenter mes résultats de test pour SymmetricDS et Bucardo, ça complètera tes retours.

Bon après je sais pas quand est-ce que je ferais ce journal, mais ça devrait finir par arriver ><

Autre article

Posté par geb () le 20/06/2009 à 21:25. (lien). Évalué à 5.

A noter l'excelent article de l'auteur de haproxy sur http://www.1wt.eu/articles/2006_lb

Revenir en haut de page