La stack techno qu’on utilise pour faire un site Web, et pourquoi


Une stack techno n’est pas une référence. Il n’y a pas de combo absolu qui rox absolument tout, c’est une question de contexte technique, financier, humain…

Mais c’est vrai que ça aide bien d’avoir sous les yeux les pratiques des autres.

Je ne vais pas expliquer pourquoi Python, je l’ai déjà fait.

Commençons plutôt par la partie purement Web, pour laquelle on utilise Django, le framework Web Python.

Max et moi avons tout deux fait du PHP avant, j’ai tâté des frameworks internes, du Symfony et plus tard du Zope. J’ai regardé du côté de Pyramid et de ses prédécesseurs, et Django est celui qui me plaît le plus. J’ai juste un peu forcé la main à Max :-)

Car oui, le framework a été avant tout un choix de goût.

Ce n’est pas un choix de performances : le framework n’a aucun impact dessus. Aucun. Les architectures ont un impact. Le framework, non. Votre bottleneck sera sur les IO, pas sur le CPU. Le choix de technos asynchrones peut avoir un impact, mais ce n’est pas une question de framework. Tornado, Twisted ou NodeJS, on s’en fout.

Donc Django, essentiellement parce qu’il me plait. Et il me plaît pour ces raisons :

  • Il y a un bon équilibre entre découplage et intégration. En général c’est soit très découplé et mal intégré, soit très bien intégré et très couplé.
  • C’est bien foutu et bien documenté. Et c’est stable. Vraiment très stable. Les core devs sont hyper sérieux.
  • C’est très versatile et ça peut faire plein de trucs out of the box, petits comme gros.
  • C’est assez facile à apprendre. Ça reste un framework, donc ce n’est pas la plus simple des démarches, mais dans le royaume des frameworks de cette taille, ça reste vraiment le plus simple.
  • La communauté est fantastique : il y a des centaines d’apps qui couvrent pratiquement tous les besoins.
  • Et bien entendu, c’est en Python.

En terme de base de données, on a fait du MySQL pendant longtemps. Ça a plutôt bien marché. Maintenant je commence mes nouveaux projets avec PostGres, qui est plus solide. Parfois je fais juste du Sqlite, parce que ça suffit.

Pas de NoSQL. Après plusieurs expériences avec MongoDB et CouchDB, je n’ai pas été convaincu que les bénéfices dépassaient le coût. Il faudrait un article complet là-dessus (qu’on m’a d’ailleurs demandé).

Question OS. c’est du CentOS avec Max (il a plus l’habitude) ou du Ubuntu Server pour mes autres projets. Je reste sur les LTS. Ce n’est pas un choix très réfléchi, c’est surtout par habitude.

Pas de machine virtuelle. On a essayé, sans y trouver un grand intérêt :

  • Il faut quand même faire des scripts de migration, donc autant s’en servir pour le déploiement.
  • On perd en perfs.
  • Les erreurs liées au mal-fonctionnement d’une VM sont absolument indébuggables.
  • Si on ne fait pas la VM soit-même, il faut mettre ses couilles dans les mains d’un prestataire de service. J’ai horreur de ça.
  • Trouver des gens avec la compétence pour gérer une VM, c’est difficile. Un script de déploiement, c’est du code que tout dev saura déjà lire. Par extension ça veut dire que je m’y replonge facilement des semaines plus tard.

Et donc pour le déploiement, j’utilise fabric, avec fabtools.

Ce n’est pas la solution la plus efficace, d’autant que ça limite à Python 2.7, mais c’est la plus simple. C’est juste du code Python. N’importe qui peut comprendre le déploiement en 15 minutes. Ça se modifie vite, s’adapte facilement.

Il faut comprendre qu’on a jamais plus d’une dizaine de serveurs pour un projet, ces choix sont donc faits en fonction de cela. Il va sans dire que si vous gérez un parc de centaines de machines, ça ne sera pas du tout le même choix technique. Peut être que Chef ou des VM seront alors carrément plus intéressants. Peut être que le NoSQL et sa capacité au scaling sera bien plus rentable.

Il ne s’agit pas de décrier les technos que nous n’utilisons pas. Il s’agit juste de dire, voilà les choix que nous avons faits, dans tel contexte, pour telles (bonnes ou mauvaises) raisons.

Durant les dernières années, on a ajouté Redis à notre stack. C’est un outil fantastique qui sert à tout : de la base de données pour les trucs simples (il y a des fois ou un schéma est overkill) à la solution de caching. C’est ce qu’on a de plus proche du NoSQL.

L’outil est tellement simple à installer (vraiment le degré zero de la maintenance, c’est beau) et à utiliser que ça ne vaut juste pas le coup de s’en priver.

Du coup, plus de memcache. Toutes les grosses requêtes sont sauvegardées dans Redis, dès qu’on fait un script qui a besoin de persistance temporaire, Redis, pour communiquer entre plusieurs process, Redis, pour toutes les opérations qui ont besoin de grosses perfs comme les stats, Redis. Vive Redis.

D’ailleurs on utilise Redis aussi comme broker pour notre gestionnaire de queues et de taches : celery. Si vous pythonez, je vous recommande chaudement celery pour toutes les tâches en background, les crawlers, les chaînes de process, etc.

On a aussi du moteur de recherche. Là on tape dans du Solr (avec haystack). C’est très puissant, en tout cas syntaxiquement car ça ne fait pas de sémantique. Ne vous attendez donc pas à rattraper Google. Mais c’est aussi méga chiant à configurer et très lourd. Je pense qu’un jour on va migrer sur ElasticSearch, mais c’est pas la priorité. Don’t fix what ain’t broken.

Devant tout ça on a Nginx. Comme beaucoup on a fait Apache => Cherokee => lighttp => nginx. Et franchement, je ne reviendrai jamais en arrière : plus léger, plus rapide, plus facile à installer et à configurer, plus versatile. Nginx fait tout, et mieux.

En proxy on a du gunicorn. Parce qu’on avait la flemme de configurer uwsgi et qu’on a pris l’habitude.

Après on utilise plein de libs, de petits outils, etc. Mais ça c’est le gros de notre archi.

33 thoughts on “La stack techno qu’on utilise pour faire un site Web, et pourquoi

  • Dseed

    Salut,
    Juste une petite question, vous dites a la fin utiliser nginx en reverse proxy et vous utilisez en serveur gunicorn? Et plus apache pour faciliter l’int de ngnix c’est bien ca ? Je maitrise pas cette partie … ;) merci

  • Alexis

    J’utilise quasiment la même stack !
    Pour le déploiement je me suis fait un petit hook git sur mon serveur qui s’occupe de tout (un peu à la Heroku :p)

    Pour les VM en effet je n’ai pas trouvé beaucoup d’intérêts. Mais je commence à me pencher sur le projet Docker (docker.io) qui permet de gérer des containers lxc. Ce dernier n’étant pas encore stable il est déconseillé de l’utilisé pour de la prod mais il reste très prometteur.

    Concernant ElasticSearch je risque de partir sur cette solution pour un futur projet (il me tarde de tester tout ça d’ailleurs :))

  • Labarbiche

    Super article, merci !
    Et question web services, ça vous arrive d’en faire ? Ou alors vous vous en battez les tastypie et faites pas de REST dans vos projets ?
    Autre chose, vous avez pas quelques RabbitMQ dans un clapier en arrière baie 8U ?

  • raphi

    Même question que Dseed. nginx, ok, je vois c’que c’est, mais gunicorn, ca fait un moment que j’vois l’nom un peu partout, mais j’ai toujours pas bien pigé ce que c’est ou a quoi ca sert concretement.

  • G-rom

    Ça permet de servir votre application sans utiliser le serveur de dev flask / django / …

    Nginx est là pour servir les statics et reverse proxy vers l’app.

  • Max

    Sam a oublié de dire qu’on utilisait Varnish en cache, sa tue sa race ^^

    Et récement du Lua dans NGinx pour commander nos serveurs de contenu (c’est uns sorte de web service ou soap ou rest, j’en sais rien du nom que ça a) en gros on dit à nos serveur via des commandes http d’aller chercher du contenu sur d’autres serveurs, le tout toujours en http via url sécurisés, plus besoin de rsync, de clefs ssh, etc, et c’est plus rapide.

  • Sam Post author

    @Dseed: c’est ça, mais pas d’apache.

    @Labarbiche: pour les apis simples, on utilise django-quicky à la mano. Pour les apis complexes, c’est django-rest-framework. Plus de RabbitMQ, c’est trop chiant à setuper et ça apporte rien par rapport à Redis pour nos besoins.

    @raphi: gunicorn est un serveur wsgi, c’est l’intermédiaire entre nginx, qui est un serveur de fichiers statiques, et ton site web dynamique.

  • groug

    Merci pour cet article très intéressant !

    Je me suis pris une petite Dedibox il y a de ça une semaine (commande estimée à plusieurs jours, livrée 27 minutes plus tard, ssh accessible après 1/2 d’installation d’Ubuntu Server 12.04, bluffant), dans l’idée de bricoler quelques trucs dessus (en Python), et tout ceci étant nouveau pour moi, je me suis lancé avec Apache/CherryPy/Flask/sqlite avec comme premier projet un Shaarli-like (j’ai un projet semi-pro de jeu multi asynchrone sur Android depuis le début de l’année, et j’utilise bottle/cherryPy/mongoDB chez Heroku pour le serveur, et quand j’aurais la maîtrise de mon serveur perso, je tâcherais de migrer tout ça). A ce propos, pour avoir testé Bottle et Flask, je préfère nettement Flask. Je trouve la doc mieux faite, apprécie le système de templating et trouve le principe des filters très ingénieux.

    Depuis, j’ai lu beaucoup de bien de nginx, et votre message me confirme qu’il faudrait que je remplace Apache.

    Pour CherryPy, y a-t-il un intérêt à passer à gunicorn, ou les deux se valent, s’il ne s’agit de les utiliser qu’en tant que serveur wsgi ?

    Ca fait plusieurs fois que vous mentionnez Fabric (dont un article), la prochaine étape pour moi sera de m’en servir pour automatiser le déploiement.

  • Sam Post author

    Gunicorn a des partis écrites en C, il est plus rapide mais demande compilation.

  • LeMeteore

    Holla,
    Pour les VMs, je fais du lxc, docker c’est chelou.
    Pour le deploiement, je suis entrain d’experimenter Ansible.

    Merci pour le post

  • raphi

    @sam:
    Du coup si j’pige bien, ca remplace plus ou moins le mod_wsgi qu’on utilise avec apache ?
    J’avais du mal a piger le coup d’avoir deux serveurs differents sur la même bécane, mais du coup, pour la séparation execution/fichier statiques, c’est pigé, merci ^^

    @groug:
    J’avais envie de faire la meme chose, puis finalement j’ai eu la flemme et j’me suis pris un compte chez webfaction. Moins intéressant sur le plan apprendre à bidouillant, mais bon, tanpixe. J’avais vu pas mal de bons avis sur les dedibox, ton message me fait un peu regretter mon choix, en tout cas si tu as d’autres retours je suis preneur ^^

  • foxmask

    je ne comprends pas ça :

    Ce n’est pas un choix de performances : le framework n’a aucun impact dessus. Aucun. Les architectures ont un impact. Le framework, non. Votre bottleneck sera sur les IO, pas sur le CPU.

    on a des tonnes de pages de comparatifs de perf de framework. On choisi donc bien un framework aussi en fonction de ses perfs non ? si pour faire un simple “hello word” le framework traverse 200 classes ; c’est bien un pb du framework et qui agira sur les perf in fine ?

  • mdp

    Très bon article.

    Pour ma part je bosse avec un contexte sécurité très présent, donc j’ai de petites particularités au niveau du déploiement.

    La machine de déploiement n’est pas la même que la machine de production par exemple (d’ailleurs la première n’est active que lors d’un déploiement). De cette manière ça évite d’installer des merdes sur la machine de prod qui élargirait le potentiel périmètre de compromission. Elle est minimaliste et ne fournit que le service pour lequel elle est prévu. Absolument rien d’autre. Elle n’a d’ailleurs accès à rien (sauf si elle doit communiquer avec d’autres services) ce qui évitera de la transformer en relai à bouse si elle se faisait compromettre.

    Forcément, pour faciliter la tache, il faut que la prod et la préprod soient identiques en term de conf. Pour cette raison on utilise des VMs qui sont quand même géniales pour gérer ça sans collectionner des baies.

    Si la charge est amenée à monter, on a aussi l’avantage de pouvoir cloner les VMs et les déployer en pagaille derrière un load balancer, mais bon normalement, pas besoin d’en arriver là.

    Bon tout ça c’est pas vraiment lié à la stack mais plutot à l’archi… mais ça compte beaucoup, et c’était pour rebondir sur les propos concernant les VMs.

    Du coup, je vais en profiter pour parler un peu de la stack que j’utilise.

    Niveau OS et serveur http, on change pas une équipe qui gagne, donc CentOS + nginx.

    Au coeur il y a Flask avec une surcouche maison pour faire des services RESTful en deux temps trois mouvements (bien stricts au niveau du respect du concept). Ces services sont éventuellement enrichis par des UIs dont le comportement est entièrement laissées à la charge d’une application AngularJS (parce que bordel que c’est cool) la partie serveur se chargeant de livrer ce qu’il faut en fonction des besoins (et des droits).

    L’avantage de Flask, c’est quand même son minimalisme et du coup, c’est l’opportunité de concevoir une plateforme bien ad-hoc à ses besoins ça demande sans doute un peu plus de boulot qu’un framework full-featured comme Django, mais ça évite aussi de tordre son problème pour essayer de le faire rentrer dans le modèle prévu par le framework (cas de figure qui est un vrai cauchemar quand on le rencontre).

    Pour le stockage des données, c’est en fonction des besoins donc en fonction des projets il y a du Postgre, du Redis (surtout pour le caching) et/ou du ElasticSearch.

    En résumé ça donne des VMs avec CentOS / nginx / uwsgi / werkeug / flask

  • Sam Post author

    @foxmask: non c’est du bullshit. On choisit une techno pour ses perfs dans certains domaines (par exemple asynchrone VS synchrone) mais pas un framework. A technos et usages égaux, ils se valent. Tu auras une différence localisée, mais l’ordre de grandeur est équivalent, et ça suffit largement.

    Languages, libraries and frameworks don’t scale. Architectures do.

    — Cal Henderson

  • Sam Post author

    @mdp: quand on a un spécialiste pour les VM attachée à l’équipe, voir carrément un sysadmin à plein temps, la VM fait gagner pas mal de temps, c’est sûr.

  • residante

    Idem que mdp, c’est flask flask et flask ! Je l’utilise depuis sa sortie presque, et je n’ai jamais été bloqué par le framework, aussi bien sur les petits que les gros projets. C’est vraiment agréable de travailler avec des projets opensource comme Flask.

    J’utilise également fabric+fabtools pour le déploiement.

    Depuis peu je m’essaye a vagrant, qui permet de reproduire des machine de dev sur demande. C’est vraiment cool comme outil de virtualisation pour le développement. D’ailleurs mon Vagrantfile fait juste appel à fabric (fab bootstrap) pour lancer le projet dans une nouvelle machine. De cette maniérè, j’ai ma machine de dev qui a la même configuration que ma machine de prod à moindre effort. (Docker j’ai essayé, mais pas assez convaincant, je reste sur lxc).

    Pour les serveurs d’applications, j’ai longtemps utilisé le module WSGI de gevent, puis un peu de gunicorn et autres. Mais j’ai toujours pas d’avis pertinent. Si quelqu’un a fait un petit comparatif sur les différents serveurs WSGI, je suis preneur :)

  • groug

    @raphi : pour l’instant, je n’ai pas grand chose à dire, ça fait une semaine que ça tourne, et je n’exploite pas beaucoup. J’avais essayé de commander chez eux il y a quelques mois, mais grosse blague : tu peux t’inscrire de l’étranger sans souci, mais une fois inscrit tu ne peux pas commander. Le support me disait qu’il fallait obligatoirement commander depuis la France. J’ai essayé via mon frère en France, mais ça ne fonctionnait pas non plus : le compte était bloqué. J’ai dû faire fermer le compte, sauf qu’en vrai, ils l’ont juste désactivé, mes infos y étaient toujours et je ne pouvais pas en recréer un. J’ai dû râler sur twitter, on me l’a vite supprimé. J’ai voulu attendre les nouvelles offres OVH, sauf que ça fait tellement longtemps que j’attends que j’en ai eu marre : lors de ma dernière conversation avec mon frère sur Hangouts, j’ai activé le bureau à distance (ça vaut pas TeamViewer mais ça dépanne) et j’ai retenté une inscription : banco !
    En une semaine, j’ai quand même eu 2 reboots suites à un ping down (il y a un système de monitoring qui reboote si le ping ne répond plus), et ça c’est inquiétant (est-ce le monitoring qui est un peu trop sur les nerfs ?). J’attends de voir si ça recommencera, dans ce cas je contacterais le support.

    En tout cas, vu la facilité déconcertante pour commander et installer un OS par l’interface, je recommande !

  • lordi

    Les Frameworks, c’est pas le truc pour les débutants en informatique ?
    Un vrai dev, il code pas avec ces machins ! Il CREE.

    Au passage, ça me fait un peu mal là, des conseils de dev de quelqu’un qui utilise WordPress pour son propre site.

  • raphi

    @groug:
    Merci pour les infos ^^
    On m’avait parlé des équivalents OVH, je m’orientais plus la dessus au debut (simplement parceque c’est de ça qu’on m’avait causé), puis itou, la flemme d’attendre.

  • groug

    Je suis en train de jouer avec Fabric+Fabtools et Supervisor (et en profite pour basculer d’Apache à nginx, et tester gunicorn. Quel mouton je fais !), c’est chouette, très chouette ! Je jubile de voir à quel point c’est simple :’)

    Petite question, à S&M et aux autres : vous utilisez quelle version de Supervisor ?
    Parce que fabtools.require.supervisor cherche à l’installer non pas par pip mais par apt-get, et la version du paquet sur Ubuntu 12.04 (et 13.04 aussi, d’ailleurs) est la 3.0a8 qui date de janvier 2010. Le site officiel de supervisor recommande justement easy_install/pip pour avoir une version récente.

    Parce que si c’est important d’avoir une version récente, ça veut dire qu’il faut éviter fabtools.require.supervisor et utiliser directement fabric, et dans ce cas je me demande s’il n’y a pas d’autres éléments comme ça dans fabtools qui font qu’au bout d’un moment on se retrouve à tout refaire soi-même.

  • Sam Post author

    On a jamais fais attention à la version de supervisor utilisée. Ca marche tout seul.

  • Ronan Amicel

    @groug si tu as retours ou des suggestions d’améliorations pour le support de supervisor dans fabtools, n’hésite pas à ouvrir une issue sur github !

  • groug

    @Ronan : je viens de voir ton message, j’ai ouvert une issue sur le sujet, merci !

  • Mathieu

    @groug: j’ai eu le même problème sur mes ubuntu-server. Tu peux demander à Fabtools de t’installer supervisord pour tout le monde depuis pip, comme ça t’as la dernière version, system-wide :)

  • Bob

    Au niveau de la terminologie, c’est pas plutôt nginx le proxy et gunicorn le serveur ?

  • Sam Post author

    Techniquement, les deux sont proxies et servers.

    Nginx est server du point de vu du client web, et proxy de gunicorn, gunicorn est server du point de vu de nginx, et proxy de django.

  • bob

    Salut,

    J’utilise MySQL/phpmyadmin depuis toujours et j’ai pas à m’en plaindre, mais certaines nouvelles fonctionnalités de Django que je trouve sympa sont «PostGres only», alors je vais peut être faire la bascule.

    Il existe un tas d’outils graphiques (PgAdmin par exemple ) pour administrer les bases, t’en a un à conseiller ?

  • Keanu_ribs

    Merci pour l’article.

    4 ans après, le constat suivant est-il toujours d’actualité ? Peut-être que l’article complet a été écrit depuis ?

    ” Pas de NoSQL. Après plusieurs expériences avec MongoDB et CouchDB, je n’ai pas été convaincu que les bénéfices dépassaient le coût. Il faudrait un article complet là-dessus (qu’on m’a d’ailleurs demandé). ”

  • Sam Post author

    Toujours pas de NoSQL, maintenant que PostGres a un super support de BJSON, ça se justifie encore moins. Il existe des raisons d’utiliser du NoSQL si on a besoin de réplication à très grosse échelles, mais ce n’est pas notre cas.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.