Programmation performante des serveurs web

La performance des serveurs web est un vrai sujet : on a besoin de sites qui rĂ©pondent vite, pour vendre plus 😉

Et un serveur web peut ĂȘtre amenĂ© Ă  rĂ©pondre Ă  « pleins » de requĂȘtes simultannĂ©es.

On peut palier de maniĂšre superficielle Ă  ces problĂšmes avec du cache. Bonne idĂ©e… mais les sites doivent de plus en plus ĂȘtre personnalisĂ©s, dynamiques. On peut donc « cacher » certaines ressources, mais pour les parties dynamiques, il faut faire autrement.

Au coeur des serveurs web se pose donc la question de la programmation parallĂšle : faire tourner plusieurs programmes en parallĂšles pour rĂ©pondre en mĂȘme temps Ă  plusieurs utilisateurs.

Quand on programme avec les technologies « normales », on ne se rend pas compte de tout ça : c’est le serveur web qui gĂšre, de maniĂšre transparente pour le programmeur. en fait, Ă  chaque appel au serveur web, un fork est crĂ©Ă©. Un fork, c’est une unitĂ© d’exĂ©cution indĂ©pendante. Chaque programme, pour chaque appel, est donc « dans son coin ».

C’est une bonne idĂ©e, parce que on masque ce problĂšme technique… Sauf que la gestion des forks n’est pas trĂšs optimisĂ©e, et qu’Ă  crĂ©er trop de forks, on fait rapidement tomber les serveurs.

D’ou l’idĂ©e de faire autrement. C’est en particulier ce que propose certains environnements, tel node.js, basĂ©s sur des serveurs webs spĂ©cifiques (autre que apache donc).

Dans ces environnements alternatifs, les différents programmes ne sont pas exécutés dans des forks indépendants.

Pour gĂ©rer la continuitĂ© entre les diffĂ©rentes fonction, le programmeur doit mettre en place des procĂ©dures de call back, …

Bref, je ne veux pas trop rentrĂ© dans les dĂ©tails (d’ailleurs, je ne suis plus programmeur, j’atteints vite mes limites 😉 ).

Mon sentiment sur cette histoire :

Je comprends le chemin empruntĂ© par ces solutions, c’est pragmatique : puisque les serveurs web rament avec les technos de forks, on descend d’un niveau, et on gĂšre la programmation parallĂšle directement.

Mais sur le fond, je suis convaincu que la solution n’est pas lĂ . Cela me semble complĂštement indispensable de masquer ces problĂ©matiques au programmeur, qui a dĂ©jĂ  bien de quoi s’occuper. Et si la programmation parallĂšle n’est pas efficace, et bien il faut revoir l’architecture du systĂšme !

12 commentaires

  1. Les serveurs web, n’ont aucun soucis avec les threads, qui d’ailleurs sont gĂ©rĂ©s par l’OS au niveau du scheduling et non par la partie applicative.

    Puisque tu mentionnes Apache, je pense que tu confonds thread et fork d’ailleurs. Apache couplĂ© avec PHP fonctionnant avec le module prefork en trĂšs grande majoritĂ©, soit des forks.

    Il faut savoir qu’un fork n’est pas un thread. En « forkant » le programme se clone intĂ©gralement en mĂ©moire pour prendre un chemin d’execution diffĂ©rent. C’est lent Ă  la crĂ©ation, ça consomme de la mĂ©moire, mais c’est trĂšs simple de fonctionnement. Chaque fork est totalement indĂ©pendant des autres. C’est ce que tu sembles vouloir dĂ©crire dans ton post.
    Dans les threads une connexion et une mĂ©moire partagĂ©e est gardĂ©e avec son parent. Ce qui en simplifie la crĂ©ation et ouvre la porte Ă  une communication inter-processus. Ce qui peut s’avĂ©rer pratique mais cela ouvre aussi la porte Ă  la gestion des lock, mutex, zone de synchronisation de la mĂ©moire partagĂ©e
 qui entraine bien souvent blocage, goulot d’Ă©tranglement etc
 il n’y a qu’Ă  regarder le Java et ces nombreux soucis Ă  ce niveau. C’est un sujet difficile Ă  maitriser et assez ouvert aux erreurs.

    Il existe d’autre mode de fonctionnement permettant de gĂ©rer ou simuler du multi processus comme les green-threads, co-routines, etc
, avec d’autres avantages mais aussi d’autres inconvĂ©nients. La plupart offre une gestion plus rapprochĂ©e du langage de programmation et indĂ©pendante de l’OS, gĂ©nĂ©ralement plus efficace et plus facile Ă  programmer mais au prix d’un fonctionnement bien moins souple.

    Il faut comprendre la nature mĂȘme du web qui depuis toujours pour le HTTP est un protocole dĂ©connectĂ© et sans Ă©tat. Chaque requĂȘte est indĂ©pendante de ses consoeurs et le fork se prette magnifiquement Ă  ce type de fonctionnement contrairement aux autres opportunitĂ©s. De plus, les sessions et cookies apportent le minimum pour palier au besoin rudimentaire de garder un Ă©tat entre deux requĂȘtes.

    Seulement aujourd’hui le volume de requĂȘte, les processeurs multi-coeur, l’arrivĂ©e du web dit connectĂ©, entre autre mais pas seulement, ajoutent de nouvelles inconnues Ă  l’Ă©quation.
    Aujourd’hui les technologies s’adaptent et proposent de nouvelle solution. C’est pourquoi dans Php d’autres solutions se sont prĂ©sentĂ©es comme FPM, German, utilisation de ZeroMQ pour ne citer que cela


    « Masquer le problĂšme » est un terme incorrect. Je dirai qu’Ă  leur actuelle la gestion des processus est reportĂ©e au serveur web par exemple.
    Pour un programmeur il vaut mieux ĂȘtre au fait de ces Ă©lĂ©ments mĂȘme si il ne les emplois pas directement dans le dĂ©veloppement web. Chose qui devrait changer car de plus en plus on a le besoin justement d’apporter une communication interprocess ; peu importe comment ce fait celle-ci.

    Bref la « scalabilitĂ© » d’un systĂšme, prend en compte un nombre trĂšs large d’Ă©lĂ©ments Ă  commencer par les besoins du dit systĂšme et ne se limite pas Ă  la question du thread ou pas thread. C’est une problĂ©matique Ă  abordĂ©e dans son ensemble et pour ma part, elle ne se rĂ©flĂ©chie pas comme tu viens de le faire.

  2. Merci Alban,

    Effectivement, tu as raison, j’ai confondu Thread et Fork, j’ai corrigĂ© l’article suite Ă  ton commentaire

    Merci encore pour ces infos, c’est le cĂŽtĂ© gĂ©nial du blog, que d’avoir de tels commentaires 🙂

  3. Je ne suis pas d’accord sur ton sentiment:

    node.js et cie n’est pas juste un nouveaux serveur web un peu plus performant que les autres. Il s’agit d’un changement de paradigme : la programmation asynchrone. Cela permet de dĂ©coupler l’Ă©criture du programme de la gestion du parallĂ©lisme. Cela permet de distribuer plus facilement les traitements sur les processeurs et serveurs disponible.

    C’est pour moi un changement d’architecture qui permet justement de se dĂ©tacher des problĂšmes liĂ©s Ă  l’exĂ©cution concurrente, au prix d’une nouvelle façon de penser et d’Ă©crire les programmes.

  4. @Nicolas> Oui, j’avais bien compris ce changement de paradigme. Mais ça me donne l’impression que ce changement rajoute plutĂŽt de la complexitĂ© cĂŽtĂ© programmation, avec comme raison la performance du serveur.

  5. Je t’en prie 🙂

    N’oublie pas que Apache ne se restreint pas Ă  son module prefork (gestion par fork) mais il Ă  aussi une gestion par thread (module worker), on peut aussi lui indiquer une gestion externe des process (exemple avec FPM).
    On restreint beaucoup trop souvent Apache Ă  son utilisation la plus courante malheureusement.

    De mĂȘme certains langage dans la conception de leur interprĂ©teur sont plus apte que d’autre Ă  la gestion multi process. Le GIL (Global Interpreter Lock) est gĂ©nĂ©ralement un point noir en la matiĂšre. Le moteur V8 de Google sur lequel se base sur Node.js est conçu pour ĂȘtre performant Ă  ce niveau.

    http://fr.wikipedia.org/wiki/C10k_problem est un bon point de départ sur le sujet des perf des serveurs web.

    Aujourd’hui je dirai que la techno en terme de serveur web importe moins qu’avant. MĂȘme si elle reste trĂšs importante, elle n’est plus cruciale, due au progrĂšs apportĂ©s en matiĂšre de « cloud ». Aujourd’hui on multiplie les instances de serveurs en un claquement de doigt, tout en gardant les dĂ©veloppement simple et avec une gestion fine des coĂ»ts


  6. @Alban> Merci pour le lien, je ne connaissais pas et c’est effectivement super intĂ©ressant.

    A propos du cloud : a court terme, tu as raison, mais je pense que la « pensée écolo », la limite des ressources naturelles va changer ça dans les années à venir.

  7. La programmation fonctionnelle n’est pas forcement plus complexe, c’est juste une nouvelle façon de penser. J’ai dĂ©jĂ  vu (trop) de services Ă©crit en langages impĂ©ratifs beaucoup trop complexe…

    La solution a plus long termes pourrait-ĂȘtre dans le code off-loading: on transfert les traitements de l’utilisateur sur son pĂ©riphĂ©rique (cf https://www.usenix.org/conference/osdi12/toe-transparent-offload-engine)

  8. Merci, il se pourrait que le cloud soit justement une des rĂ©ponses Ă  la « montĂ©e Ă©colo » qui rappelle le besoin accrue de limiter les consommations d’Ă©nergie.

    Je m’explique sur ce point de vue :

    Avoir 1000 instances d’un serveur web aujourd’hui ne signifie pas qu’il y a 1000 servers physique derriĂšre (de l’ordre d’un 2U mono Xeon par exemple) comme dans le passĂ©.

    Aujourd’hui des centaines d’instances peuvent ĂȘtre gĂ©rĂ©es par une seule machine physique (de l’ordre par exemple d’un 64 coeur avec 256 Go de ram couplĂ© Ă  une bais de disque).

    Ce genre de catĂ©gorie de machine trĂšs puissantes et trĂšs onĂ©reuse, hier rĂ©servĂ©es Ă  de grands compte, sont aujourd’hui massivement employĂ©e pour Ă©tablir des clouds. À terme on peut estimer que dans les datacenters des milliers de petits serveurs vont ĂȘtre remplacer par des « super-calculateurs » offrant Ă  surface identique, Ă©nergie identique, une capacitĂ© de service beaucoup plus importante.

    Plus le cloud progresse dans ses technologies, plus les ressources physiques sont idĂ©alement rĂ©parties et utilisĂ©es, moins ont a besoin d’en produire et de les alimentĂ©es (Ă  besoin Ă©gaux mais ceux-ci sont loins de ce stabiliser n’est-ce pas…). De plus en plus on loue du calcul, de la mĂ©moire, de l’espace disque, on ne loue plus un local en datacentre, une machine physique.

    De mĂȘme les datacenters font preuvent d’innovation en matiĂšre de refroidissement, 50 % de l’Ă©nergie consommĂ©e rappelons le, OVH en france avec sont dernier datacenter est bien placĂ© sur ce crĂ©neau, et c’est une bonne chose d’une maniĂšre gĂ©nĂ©rale.

    Ceci dit, je ne sais pas de quoi l’avenir sera fait, tant qu’on consomme moins ! Et surtout qu’on le fasse Ă  moindre coĂ»t pour la planĂšte.

  9. le serveur NGinx (dont tu avais parlĂ© il me semble il y a quelques mois) permet d’Ă©viter la multiplication des process (ou fork) en gĂ©rant tous les traitements en un minimum de threads / processus (environ 4 ou 5 pour un serveur php classique).

  10. @Olivier> Hello Mr Olivier 🙂

    Oui, on a donc plusieurs paramĂštres pour aider Ă  faire des serveurs performants (serveur HTTP, Langage de programmation, …). J’ai peut ĂȘtre tord, mais je trouve que tout ça est encore d’assez bas niveau : ça marche mais faut fouiller et retrousser ses manches. Je pense qu’Ă  l’avenir, pas forcĂ©ment proche, on aura des couches d’abstractions plus Ă©voluĂ©es.

  11. @François

    Je doute pour ma part que l’abstraction soit une solution. l’abstraction induit une certaine paresse de la part des dĂ©veloppeurs. On le voit en Java ou l’abstraction de la gestion mĂ©moire produit des conso mĂ©moire dĂ©lirantes : on voit rĂ©apparaitre des OoM (out of memor) comme aux temps glorieux des dĂ©buts de J2EE (souviens toi Wokup 🙂 )
    IL ya surement moyen de concevoir un langage / couche d’abstraction qui faciliterait l’execution asynchrone plutot que synchrone mais sans rĂ©elle comprĂ©hension de ces modes d’exĂ©cution et de leurs implications au niveau systĂšme on tombera rapidement dans des travers.

    Ceci si tu as une idĂ©e mĂȘme vague de ce que tu aimerais voir Ă©merger, je veux bien apporter mes connaissances techniques 🙂

  12. Tu as peut ĂȘtre raison, on verra.

    Pour ma part, je suis sur un nouveau projet de startup, toujours du logiciel, mais fini les projets « universels » : il s’agit du dĂ©veloppement d’une brique tout ce qu’il y a de plus mĂ©tier 😉 A suivre, sur ce blog ou ailleurs 🙂

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *