Serveur HTTP Apache Version 2.4

| Description: | Une variante du MPM workerconçue pour ne
mobiliser des threads que pour les connexions en cours de traitement | 
|---|---|
| Statut: | MPM | 
| Identificateur de Module: | mpm_event_module | 
| Fichier Source: | event.c | 
Le module multi-processus (MPM) event est conçu
    pour permettre le traitement d'un nombre accru de requêtes
    simultanées en déléguant certaines tâches
    aux threads d'écoute, libérant par là-même les
    threads de travail et leur permettant de traiter les nouvelles requêtes.
Pour utiliser le MPM event, ajoutez
    --with-mpm=event aux arguments du script
    configure lorsque vous compilez le programme
    httpd.

 AsyncRequestWorkerFactor
 AsyncRequestWorkerFactor CoreDumpDirectory
 CoreDumpDirectory EnableExceptionHook
 EnableExceptionHook Group
 Group Listen
 Listen ListenBacklog
 ListenBacklog MaxConnectionsPerChild
 MaxConnectionsPerChild MaxMemFree
 MaxMemFree MaxRequestWorkers
 MaxRequestWorkers MaxSpareThreads
 MaxSpareThreads MinSpareThreads
 MinSpareThreads PidFile
 PidFile ScoreBoardFile
 ScoreBoardFile SendBufferSize
 SendBufferSize ServerLimit
 ServerLimit StartServers
 StartServers ThreadLimit
 ThreadLimit ThreadsPerChild
 ThreadsPerChild ThreadStackSize
 ThreadStackSize User
 UserLe MPM event s'inspire du MPM worker qui
implémente un serveur hybride multi-processus et multi-threads. Un processus de
contrôle unique (le parent) est chargé de lancer des processus enfants. Chaque
processus enfant crée un nombre de threads serveurs défini via la directive
ThreadsPerChild, ainsi qu'un thread
d'écoute qui surveille les requêtes entrantes et les distribue aux threads de
travail pour traitement au fur et à mesure de leur arrivée.
Les directives de configuration à l'exécution sont identiques à celles que
propose le MPM worker, avec l'unique addition de la directive
AsyncRequestWorkerFactor.
Ce module MPM tente de résoudre le "problème keep alive" de HTTP. Lorsqu'un client a effectué une première requête, il peut garder la connexion ouverte et envoyer les requêtes suivante en utilisant le même socket, ce qui diminue considérablement la charge qui aurait été induite par la création de nouvelles connexions TCP. Cependant, le fonctionnement du serveur HTTP Apache impose de réserver un couple processus enfant/thread pour attendre les données en provenance du client, ce qui présente certains inconvénients. Pour résoudre ce problème, le MPM Event utilise un thread d'écoute dédié pour chaque processus pour gérer les sockets d'écoute, tous les sockets qui sont dans un état de connexion persistante, les sockets où les filtres de gestionnaire et de protocole ont fait leur travail, et ceux pour lesquels la seule chose restant à faire est l'envoi des données au client.
Cette nouvelle architecture, en exploitant les sockets non blocants et
    les fonctionnalités des noyaux modernes mis en valeur par
    APR (comme epoll de Linux), n'a plus besoin du
    Mutex mpm-accept pour
    éviter le problème de "thundering herd".
La directive AsyncRequestWorkerFactor permet de
    définir le nombre total de connexions qu'un bloc processus/thread peut
    gérer.
Avec les MPM précédents, les connexions asynchrones nécessitaient
	un thread de travail dédié, mais ce n'est plus le cas avec le MPM Event.
	La page d'état de mod_status montre de nouvelles
	colonnes dans la section "Async connections" :
write() vers le socket
	    renvoie en général EWOULDBLOCK ou EAGAIN
	    pour que l'on puisse y écrire à nouveau après un certain temps
	    d'inactivité. Le thread de travail qui utilise le socket doit alors
	    être en mesure de récupérer la tâche en attente et la restituer au
	    thread d'écoute qui, à son tour, la réattribuera au premier thread
	    de travail disponible, lorsqu'un évènement sera généré pour le socket
	    (par exemple, "il est maintenant possible d'écrire dans le socket").
	    Veuillez vous reporter à la section à propos des limitations pour
	    plus de détails.
            KeepAliveTimeout est atteint, le socket
	    sera fermé par le thread d'écoute. Les threads de travail n'ont
	    donc plus à s'occuper des sockets inactifs et ils peuvent être
	    réutilisés pour traiter d'autres requêtes.Ces améliorations sont disponible pour les connexions HTTP ou HTTPS.
Ce MPM présentait dans le passé des limitations de montée en
	puissance qui
	provoquaient l'erreur suivante : "scoreboard is full, not at
	MaxRequestWorkers". La directive MaxRequestWorkers permet de limiter le
	nombre de requêtes pouvant être servies simultanément à un moment donné
	ainsi que le nombre de processus autorisés (MaxRequestWorkers / ThreadsPerChild), alors que le
	scoreboard représente l'ensemble des processus en cours d'exécution et
	l'état de leurs threads de travail. Si le scoreboard est plein
	(autrement dit si aucun des threads n'est dans un état inactif) et si le
	nombre de requêtes actives servies est inférieur à MaxRequestWorkers, cela signifie que
	certains d'entre eux bloquent les nouvelles requêtes qui pourraient être
	servies et sont en l'occurrence mises en attente (dans la limite de la
	valeur imposée par la directive ListenBacklog). La plupart du temps, ces
	threads sont bloqués dans un état d'arrêt en douceur car ils attendent
	de terminer leur travail sur une connexion TCP pour s'arrêter et ainsi libérer
	une entrée dans le scoreboard (par exemple dans le cas du traitement des
	requêtes de longue durée, des clients lents ou des connexions en
	keep-alive). Voici deux scénarios courants :
MaxSpareThreads). Cette situation
	    est problèmatique car lorsque la charge augmente à nouveau, httpd va
	    essayer de lancer de nouveaux processus. Si cette situation se
	    répète, le nombre de processus peut augmenter sensiblement,
	    aboutissant à un mélange d'anciens processus tentant de s'arrêter et
	    de nouveaux processus tentant d'effectuer un travail quelconque.
            A partir de la version 2.4.24, mpm-event est plus intelligent et peut traiter les arrêts graceful de manière plus efficace. Voici certaines de ces améliorations :
ServerLimit. Les directives
	    MaxRequestWorkers et
	    ThreadsPerChild
	    permettent de limiter le nombre de processus actifs, alors que la
	    directive ServerLimit
	    prend aussi en compte les proccessus en arrêt graceful pour
	    permettre l'utilisation d'entrées supplémentaires du scoreboard en
	    cas de besoin. L'idée consiste à utiliser ServerLimit pour indiquer à httpd
	    conbien de processus supplémentaires seront tolérés avant
	    d'atteindre les limites imposées par les ressources du système.
            Le comportement décrit dans le dernier point est bien visible via
	mod_status dans la table des connexions avec les deux
	nouvelles colonnes "Slot" et "Stopping". La première indique le PID et
	la seconde si le processus est en cours d'arrêt ou non ; l'état
	supplémentaire "Yes (old gen)" indique un processus encore en exécution
	après un redémarrage graceful.
La gestion améliorée des connexions peut ne pas fonctionner pour
	certains filtres de connexion qui se sont déclarés eux-mêmes
	incompatibles avec le MPM Event. Dans ce cas, le MPM Event réadoptera le
	comportement du MPM worker et réservera un thread de
	travail par connexion. Notez que tous les modules inclus dans la
	distribution du serveur httpd sont compatibles avec le MPM Event.
Une restriction similaire apparaît lorsqu'une requête utilise un
	filtre en sortie qui doit pouvoir lire et/ou modifier la totalité du
	corps de la réponse. Si la connexion avec le client se bloque pendant
	que le filtre traite les données, et si la quantité de données produites
	par le filtre est trop importante pour être stockée en mémoire, le
	thread utilisé pour la requête n'est pas libéré pendant que httpd attend
	que les données soient transmises au client.
 
        Pour illustrer ce cas de figure, nous pouvons envisager les deux
	situations suivantes : servir une ressource statique (comme un fichier
	CSS) ou servir un contenu issu d'un programme FCGI/CGI ou d'un serveur
	mandaté. La première situation est prévisible ; en effet, le MPM Event a
	une parfaite visibilité sur la fin du contenu, et il peut utiliser les
	évènements : le thread de travail qui sert la réponse peut envoyer les
	premiers octets jusqu'à ce que EWOULDBLOCK ou
	EAGAIN soit renvoyé, et déléguer le reste de la réponse au thread
	d'écoute. Ce dernier en retour attend un évènement sur le socket, et
	délègue le reste de la réponse au premier
	thread de travail disponible. Dans la deuxième situation par contre
	(FCGI/CGI/contenu mandaté), le MPM n'a pas de visibilité sur la fin de
	la réponse, et le thread de travail doit terminer sa tâche avant de
	rendre le contrôle au thread d'écoute. La seule solution consisterait
	alors à stocker la réponse en mémoire, mais ce ne serait pas l'option la
	plus sure en matière de stabilité du serveur et d'empreinte mémoire.
        
Le modèle event a été rendu possible par l'introduction de nouvelles APIs dans les systèmes d'exploitation supportés :
Avant que ces APIs soient mises à disposition, les APIs
	traditionnelles select et poll devaient être
	utilisées. Ces APIs deviennent lentes si on les utilise pour gérer de
	nombreuses connexions ou si le jeu de connexions possède un taux de
	renouvellement élevé. Les nouvelles APIs permettent de gérer beaucoup
	plus de connexions et leur performances sont meilleures lorsque le jeu
	de connexions à gérer change fréquemment. Ces APIs ont donc rendu
	possible l'écriture le MPM Event qui est mieux adapté à la situation
	HTTP typique où de nombreuses connexions sont inactives.
Le MPM Event suppose que l'implémentation de apr_pollset
	sous-jacente est raisonnablement sure avec l'utilisation des threads
	(threadsafe). Ceci évite au MPM de devoir effectuer trop verrouillages
	de haut niveau, ou d'avoir à réveiller le thread d'écoute pour lui
	envoyer un socket keep-alive. Ceci n'est possible qu'avec KQueue et
	EPoll.
Ce MPM dépend des opérations atomiques compare-and-swap
    d'APR pour la synchronisation des threads. Si
    vous compilez pour une plate-forme x86 et n'avez pas besoin du
    support 386, ou si vous compilez pour une plate-forme SPARC et
    n'avez pas besoin du support pre-UltraSPARC, ajoutez
    --enable-nonportable-atomics=yes aux arguments du
    script configure. Ceci permettra à APR
    d'implémenter les opérations atomiques en utilisant des instructions
    performantes indisponibles avec les processeurs plus
    anciens.
Ce MPM ne fonctionne pas de manière optimale sur les plates-formes plus anciennes qui ne gèrent pas correctement les threads, mais ce problème est sans objet du fait du prérequis concernant EPoll ou KQueue.
libkse (voir man libmap.conf).glibc a été compilée
      avec le support pour EPoll.| Description: | Limite le nombre de connexions simultanées par thread | 
|---|---|
| Syntaxe: | AsyncRequestWorkerFactor facteur | 
| Défaut: | 2 | 
| Contexte: | configuration globale | 
| Statut: | MPM | 
| Module: | event | 
| Compatibilité: | Disponible depuis la version 2.3.13 | 
Le MPM event gère certaines connexions de manière asynchrone ; dans ce cas, les threads traitant la requête sont alloués selon les besoins et pour de courtes périodes. Dans les autres cas, un thread est réservé par connexion. Ceci peut conduire à des situations où tous les threads sont saturés et où aucun thread n'est capable d'effectuer de nouvelles tâches pour les connexions asynchrones établies.
Pour minimiser les effets de ce problème, le MPM event utilise deux méthodes :
Cette directive permet de personnaliser finement la limite du nombre de connexions par thread. Un processus n'acceptera de nouvelles connexions que si le nombre actuel de connexions (sans compter les connexions à l'état "closing") est inférieur à :
        ThreadsPerChild +
        (AsyncRequestWorkerFactor *
        nombre de threads inactifs)
    
Il est possible d'effectuer une estimation du nombre maximum de connexions simultanées pour tous les processus et pour un nombre donné moyen de threads de travail inactifs comme suit :
        (ThreadsPerChild +
        (AsyncRequestWorkerFactor *
        number of idle workers)) * 
        ServerLimit
    
ThreadsPerChild = 10
ServerLimit = 4
AsyncRequestWorkerFactor = 2
MaxRequestWorkers = 40
idle_workers = 4 (moyenne pour tous les processus pour faire simple)
max_connections = (ThreadsPerChild + (AsyncRequestWorkerFactor * idle_workers)) * ServerLimit 
                = (10 + (2 * 4)) * 4 = 72
    Lorsque tous les threads de travail sont inactifs, le nombre maximum absolu de connexions simultanées peut être calculé de manière plus simple :
        (AsyncRequestWorkerFactor + 1) *
        MaxRequestWorkers
    
ThreadsPerChild = 10 ServerLimit = 4 MaxRequestWorkers = 40 AsyncRequestWorkerFactor = 2
Si tous les threads de tous les processus sont inactifs, alors :
idle_workers = 10
Nous pouvons calculer le nombre maximum absolu de connexions simultanées de deux manières :
max_connections = (ThreadsPerChild + (AsyncRequestWorkerFactor * idle_workers)) * ServerLimit 
                = (10 + (2 * 10)) * 4 = 120
    
max_connections = (AsyncRequestWorkerFactor + 1) * MaxRequestWorkers 
                = (2 + 1) * 40 = 120
    Le réglage de la directive
    AsyncRequestWorkerFactor nécessite de connaître le
    trafic géré par httpd pour chaque style d'utilisation spécifique ; si vous
    modifiez la valeur par défaut, vous devrez par conséquent effectuer des
    tests approfondis en vous appuyant étroitement sur les données fournies par
    mod_status.
La directive MaxRequestWorkers se nommait
    MaxClients avant la version 2.3.13. La valeur
    ci-dessus montre que cet ancien nom ne correspondait pas à sa
    signification exacte pour le MPM event.
La directive AsyncRequestWorkerFactor
    accepte des valeurs d'argument de type non entier, comme "1.5".