Quelle est la capacité de Deuxfleurs ?

Publié le 27/04/2024

De part son côté atypique (de vieux PC de bureau reconvertis en serveurs derrière des connexions FTTH grands publics avec beaucoup de logiciels maisons - tricot, garage, etc.), les usager-es de Deuxfleurs ne savent pas trop quoi attendre en terme de performance. De mon point de vue d’opérateur, c’est dur également d’évaluer les capacités de Deuxfleurs, à part en disant qu’on a pensé notre solution pour mutualiser les usages, et donc que peu de machines puissent servir à beaucoup de monde.

Commençons par quelques faits : au 27 avril 2024, Deuxfleurs a 8 serveurs (3 à Orsay, 2 à Lilles, 3 à Bruxelles). Il n’y a que 2 serveurs / 8 qui reçoivent les requetes : en effet, notre configuration IPv4 ne permet pas d’avoir plus d’un répartiteur de charge HTTP par zone géographique, et notre zone géographique belge est encore en chantier. Chaque serveur est connecté en ethernet 1Gb/sec et on a 300Mbps+ entre Proximus et Free (en gros c’est une approximation de notre bande passante sur Internet, même si ça varie en fonction des destinations et du moment observé bien entendu…). Avec 2 répartiteurs de charge, on estime donc à 600Mb/s notre bande passante sur le réseau (2x 300Mb/s), bien entendu après il faut du logiciel qui puisse gérer ça.

Chaque serveur est à peu prêt identique : un ordinateur de bureau milieu de gamme de 2013. Typiquement, en terme de processeur on a du Intel(R) Pentium(R) CPU G3420 et entre 8Go et 16Go de RAM par serveur. Au total, Nomad, un de nos outils de gestion, rapporte un total de 78Go de RAM et 16 CPU (répartis en 8 machines physiques donc).

En terme de stockage, on a 4To de stockage à Lille, 1.5To à Bruxelles, 3To à Orsay. Ça fait seulement 1.5To utilisable par Garage, car on requiert une duplication sur 3 sites pour la robustesse, et Bruxelles n’a que 1.5To (c’est normal, c’est la “zone” en chantier aujourd’hui).

Avec notre politique de 200Mo/site max, ça fait quand même déjà une capacité de 7 500 sites webs. On monte à 30 000 sites webs si on considère 50Mo (la taille réservée à la création du site, avant l’augmentation du quota). Si on passe à Bruxelles à 3To pour “rattraper” les autres sites, on double le nombre de sites web hébergeables. De plus, aujourd’hui on trouve des disques durs 2.5” à 4To, ce qui veut dire qu’on pourrait passer entre 8To et 15To par zone géographique sans changer radicalement notre infrastructure (même boitier, meme enveloppe de consommation electrique, etc.). Dans ce cas hypothétique, on dépasse les 100 000 sites webs hébergeables. Bien sûr à chaque fois, c’est en supposant qu’on héberge que des sites webs : mais on peut diviser par 2 les chiffres, et se dire qu’on alloue le reste aux autres services, et ça reste étourdissant !

Se pose maintenant la question de la montée en charge, combien de requêtes/secondes on peut traiter. Aujourd’hui on a un ~10 req/sec continu (majoritairement du à Matrix et Sogo, des protocoles de chat & email respectivement au dessus de HTTP qui font du polling, c’est très en dessous côté hébergement web garage) qui n’ébranle pas franchement nos serveurs. On va donc faire du scalability testing pour voir jusqu’où on peut monter. Il faut savoir que le pire cas pour nous, c’est quand un site web devient populaire d’un seul coup, et que tout le monde s’y connecte en même temps avec un cache froid, par exemple parce qu’un tweet devient viral ou des notifications push sur mobile envoyés par une application. On va donc prendre ce cas pour notre test.

Notez que pour les notifications mobiles, plutôt que de déployer d’avantages de serveurs pour gérer le pic de trafic, il est plus avisé d’échelonner leur envoi auprès des utilisateurs. C’est à dire envoyer un premier lot de notifications à 10% des utilisateurs, attendre 20 minutes, envoyer le 2nd lot, etc. Et oui, c’est aussi bête que ça parfois…

Notre cobaye sera ce propre blog, et plus exactement sa page d’accueil et ses 8 ressources à charger. J’utilise l’outil k6 pour ce test qui n’a pas vocation à être exhaustif, pour info voici le script de test :

import http from 'k6/http';

export default function () {
  http.get('https://quentin.dufour.io');
  http.get('https://quentin.dufour.io/assets/css/style.css');
  http.get('https://quentin.dufour.io/assets/css/typo.css');
  http.get('https://quentin.dufour.io/assets/images/favicon.ico');
  http.get('https://quentin.dufour.io/assets/fonts/MerriweatherRegularLatin.woff2');
  http.get('https://quentin.dufour.io/assets/fonts/MerriweatherBoldLatin.woff2');
  http.get('https://quentin.dufour.io/assets/fonts/MerriweatherItalicLatin.woff2');
  http.get('https://quentin.dufour.io/assets/fonts/Symbola.ornements.woff2');
}

→ Accéder au rapport complet ←

Je n’ai volontairement pas poussé l’infrastructure au maximum, mais on tient sans problème 100 utilisateurs en instantané, ce qui fait ~800req/sec et 8Mo/sec de transfert de données. Sur 1 minute, ça fait 6 000 utilisateurs. Quand on était en page d’accueil sur Hacker News, on a vu que les visites s’étalaient en réalité plutot sur 1h ou 2h, meme si le trafic n’était pas réparti de manière homogene, mais plus sous la forme d’une gaussienne. Sans faire les calculs, je dirais qu’en cas de “coup de projecteur”, on peut tenir les ~10 000 utilisateurs sans trop de soucis. En informatique, on pense souvent en terme d’ordres de grandeurs. À mon avis, l’ordre de grandeur suivant, un burst de ~100 000 utilisateurs est imaginables sans remettre en question notre architecture mais avec des améliorations à différents endroits. Par contre l’ordre de grandeur suivant, 1 million, nous forcerait à repenser en profondeur notre système. Toute cette réflexion reste encadrée pour moi par deux articles très importants, C10K et C10M. Le premier date de 2003, et constate que les serveurs industriels ont la capacité de supporter 10 000 connexions simultanés, et réfléchit à comment concevoir du logiciel qui permette d’exploiter ces capacités. On pourrait dire que C10M, c’est le même constat entre 10 et 20 ans plus tard, mais que cette fois-ci on est passé à 10 millions de connexions, là encore en remettant encore à plat le logiciel qu’on conçoit. Alors bien sûr, ici on parle de connexions qui ne font pas grand chose, mais quand même, c’est pertinent de savoir où on se situe, surtout en 2024 où on écrit encore des logiciels qui ont du mal à gérer 4 ou 5 connexions simultanées…

Jusqu’ici je parle de trafic soudain, mais pour de nombreux sites, c’est un flux continu. Dans ce cas, les visites sont beaucoup plus espacées dans le temps. Mettons un site web qui s’adresse aux particuliers, d’expérience il verra une large partie de ses visites se faire entre 7h et 9h le matin, lors de la pause méridienne, disons entre 12h et 14h puis surtout le soir, de 18h à 22h, soit au total quand même 8 heures. À 6 000 utilisateurs par minutes parfaitement répartis, ça nous fait 2.9 millions de visiteurs par jours (on suppose que consulter les pages suivantes est négligeable passé la première requête). Bien sûr, mon modèle est très naïf là, et trop imprécis pour affirmer quelque chose de définitif. Mais disons que, dès lors que le trafic se lisse sur la journée, on a pas trop de mal à gérer 1 million d’utilisateurs par jour. Bon, il ne faut pas perdre de vu que ce budget de 1 million par jour, il est à partager entre tout le monde ! Mais là encore, on a les statistiques de notre côté : des abonnements Twitch aux marchandises sur Amazon en passant par la taille des instances Mastodon, on va avoir une longue traîne : un ou quelques sites webs avec beaucoup de visites, et très rapidement toute une myriade de petits sites avec très peu de visites par jour, qui se fondent dans l’épaisseur du trait. On peut donc dimensionner pour quelques gros sites et le reste suivra.

Jusqu’ici je n’ai pas évoqué le cas d’utilisateurs malveillants, qui auraient pour objectif de réaliser une attaque par déni de service. Il existe différents types d’attaque par déni de service, certaines sont du “brute force” : un concours de celui qui aura le plus de ressources. De par l’approche de Deuxfleurs, c’est évidemment un concours que l’association n’a pas vocation à mener, et donc les attaques par déni de service sont un risque à prendre en compte. À noter que parfois, dans certaines limites, les fournisseurs d’accès internet peuvent agir pour bloquer le trafic malveillant seulement - ou tout le trafic - pendant l’attaque.

Mon test n’est pas du tout exhaustif ou représentatif de tout le web statique - mais c’est le mieux qu’on ait et on devra s’en contenter pour le moment. Par exemple, un site qui serait beaucou plus lourd (image, audio) pourrait avoir un comportement différent (on atteindrait peut-être une limite de bande passante - à tester), et c’est juste un exemple parmis des milliers de situations possibles (HTTP 2 vs HTTP 1.1 ? Versions & Cipher de TLS ? etc.).

À noter aussi qu’on n’a pas passé beaucoup de temps à penser l’optimisation des ressources de Deuxfleurs, on pourrait probablement avoir des gains avec de petites modifications. Par exemple en utilisant les spécificités d’IPv6 qui permettent de mettre plusieurs load balancers par zones géographique, ou en favorisant le chiffrement ChaCha20-Poly1305 qui est plus rapide que AES sur les CPU qui n’ont pas d’accélération matérielle comme certains de nos serveurs. Côté matériel, on pourrait s’assurer qu’on a du lien gigabit partout (et donc faire la chasse au 100Mb qui trainerait). En réalité je n’ai pas vraiment réfléchi plus que ça au sujet, je suis sûr qu’en se creusant les méninges, on trouverait des choses.

Et pour terminer, une conclusion provocante : avec 10 req/sec, rarement plus de 5Mb/s de trafic sortant, et 250 sites webs hébergés, c’est respectivement 1% du budget requête, 2% de la bande passante, et 3% du budget stockage qui est actuellement utilisé sur Deuxfleurs.