Tout commence par une question : que font ces utilisateurs ? Mille personnes connectées à une application ne font pas mille requêtes par seconde, et une page servie depuis un cache coûte cent fois moins qu'une page calculée. Ce guide traduit des utilisateurs en requêtes, des requêtes en processeur et en mémoire, puis montre comment le vérifier par un test de charge.
« Utilisateurs simultanés » désigne trois grandeurs différentes selon qui parle :
On passe de l'une à l'autre par la loi de Little : le nombre de requêtes en cours est égal au débit, en requêtes par seconde, multiplié par la durée moyenne d'une requête.
Exemple. 600 utilisateurs actifs en même temps, qui déclenchent chacun une requête toutes les 20 secondes, font 30 requêtes par seconde. Si chaque requête dure 100 ms, le serveur n'a que 3 requêtes en cours en moyenne. L'enjeu est ailleurs : dans les pics et dans les requêtes lentes.
Une requête occupe le processeur le temps de son calcul : exécuter le code, interroger la base, construire la réponse. Un vCPU traite donc au plus 1 000 ÷ t requêtes par seconde, où t est le temps de calcul d'une requête en millisecondes. Le temps passé à attendre (une API externe, un disque) n'occupe pas le processeur, mais il occupe un worker.
| Type de requête | Temps de calcul typique | Par vCPU, ordre de grandeur |
|---|---|---|
| Fichier statique, ou page servie depuis un cache | Moins de 1 ms | Plusieurs milliers de requêtes par seconde |
| Page WordPress servie par un cache de pages | 1 à 5 ms | Plusieurs centaines par seconde |
| API JSON (Node.js, Go, FastAPI) avec une requête SQL indexée | 5 à 20 ms | 50 à 200 par seconde |
| Page WordPress ou Laravel calculée à chaque visite | 100 à 300 ms | 3 à 10 par seconde |
| Rapport, export, génération de PDF | 500 ms à plusieurs secondes | Moins de 2 par seconde |
Avec ces ordres de grandeur, 30 requêtes d'API par seconde à 10 ms de calcul occupent 30 % d'un seul vCPU. Les mêmes 30 requêtes par seconde sur des pages WordPress sans cache demandent 3 à 9 vCPU. Le cache de pages sert précisément à faire passer une page de la quatrième ligne du tableau à la deuxième.
Chaque requête en cours est prise en charge par un worker, et les workers occupent de la mémoire, qu'ils travaillent ou non. C'est souvent la mémoire, plus que le processeur, qui fixe le nombre de requêtes traitées en parallèle :
pm.max_children fixe le plafond : 20 processus, c’est 800 Mo à 1,6 Go.max_connections.Les connexions persistantes (websockets, notifications en temps réel) se comptent à part : ouvertes en permanence, elles occupent peu de processeur et quelques dizaines de kilo-octets de mémoire chacune. Un serveur Node.js en tient des milliers dans quelques centaines de Mo.
Sur une application réelle, le serveur sature rarement là où on l'attend. Les causes les plus fréquentes, dans l'ordre où les chercher :
pg_stat_statements sur PostgreSQL, ou le journal des requêtes lentes de MySQL, la désigne.Les ordres de grandeur donnent une première taille ; un test de charge donne la vraie. Le principe : simuler des utilisateurs de plus en plus nombreux sur une copie de l'application, et relever le moment où le temps de réponse décroche.
wrk -t2 -c50 -d30s --latency https://preprod.votre-site.com/
Pour un parcours complet (connexion, navigation, recherche), k6 décrit un scénario en JavaScript et fait monter la charge par paliers :
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 300 },
{ duration: '5m', target: 300 },
{ duration: '2m', target: 0 },
],
thresholds: { http_req_duration: ['p(95)<500'] },
};
export default function () {
http.get('https://preprod.votre-site.com/');
sleep(15);
}
htop pour le processeur, free -h pour la mémoire, les journaux pour les erreurs.L'ordre qui coûte le moins et rapporte le plus :
Les trois premières étapes couvrent la grande majorité des applications de gestion, des sites et des API : plusieurs centaines d'utilisateurs actifs en même temps tiennent sur un seul serveur bien réglé.
Le VPS Pro se décline en six tailles, sur processeurs Intel Xeon, mémoire ECC et SSD NVMe en miroir, et passe à la taille supérieure à tout moment, sans réinstallation. L'Assistance intégrale est comprise : dites-nous combien d'utilisateurs vous attendez au lancement et dans un an, nous vous conseillons la taille ; et quand une page ralentit, nous diagnostiquons et vous indiquons quoi faire, du système jusqu'au code de votre application.
Pour une API ou une application dont les requêtes prennent 10 à 20 ms de calcul, plusieurs centaines d'utilisateurs actifs en même temps. Pour un site WordPress sans cache de pages, une centaine environ. L'écart tient au temps de calcul de chaque requête et au cache, d'où l'intérêt d'un test de charge.
Le nombre de visiteurs par jour dit peu de chose : ce qui compte, c'est le pic. Pour passer de l'un à l'autre, divisez les visites de la journée par les heures d'activité, multipliez par les pages vues par visite, puis par un facteur de pointe de 3 à 5. 10 000 visites sur 10 heures, à 4 pages chacune, donnent environ 1 page par seconde en moyenne, et 3 à 5 au pic.
Trois signes : le temps de réponse monte avec le trafic, le processeur reste au-dessus de 80 % aux heures de pointe, ou la mémoire disponible tombe près de zéro. Les journaux du serveur web montrent alors des erreurs 502 ou 504, et les requêtes attendent un worker libre.
Oui : une connexion websocket reste ouverte en permanence. Elle consomme peu de processeur et quelques dizaines de kilo-octets de mémoire. Un serveur Node.js en tient des milliers ; ce sont les messages envoyés, plus que les connexions ouvertes, qui chargent le processeur.
Simafri
Parlons de votre projet
Dites-nous en deux mots ce qu'il vous faut : on revient vers vous rapidement.
Merci ! Votre demande a bien été envoyée. Nous vous répondrons rapidement.
Vous préférez l'email ? Écrivez-nous à support@simafri.com.