summaryrefslogtreecommitdiffstats
path: root/docs/manual/mod/event.xml.fr
blob: a6a9dfc5db573faab354315410c6ecb09de3e356 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.fr.xsl"?>
<!-- English Revision: 1820539 -->
<!-- French translation : Lucien GENTIS -->
<!-- Reviewed by : Vincent Deffontaines -->

<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<modulesynopsis metafile="event.xml.meta">
<name>event</name>
<description>Une variante du MPM <module>worker</module> conçue pour ne
mobiliser des threads que pour les connexions en cours de traitement</description>
<status>MPM</status>
<sourcefile>event.c</sourcefile>
<identifier>mpm_event_module</identifier>

<summary>
    <p>Le module multi-processus (MPM) <module>event</module> est, comme son nom
    l'indique, une implémentation asynchrone basée sur les évènements et 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.</p>

    <p>Pour utiliser le MPM <module>event</module>, ajoutez
    <code>--with-mpm=event</code> aux arguments du script
    <program>configure</program> lorsque vous compilez le programme
    <program>httpd</program>.</p>

</summary>

<seealso><a href="worker.html">Le MPM worker</a></seealso>

<section id="event-worker-relationship"><title>Relations avec le MPM Worker</title>
<p>Le MPM <module>event</module> s'inspire du MPM <module>worker</module> 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
<directive module="mpm_common">ThreadsPerChild</directive>, 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.</p>

<p>Les directives de configuration à l'exécution sont identiques à celles que
propose le MPM <module>worker</module>, avec l'unique addition de la directive
<directive>AsyncRequestWorkerFactor</directive>.</p>

</section>

<section id="how-it-works"><title>Comment tout cela fonctionne</title>
    
    <p>Ce module MPM a été conçu à l'origine pour 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 associé à un jeu de
    threads de travail, partageant les files d'attentes spécifiques aux
    requêtes en mode keep-alive (ou plus simplement en mode "lisible"), à celles
    en mode écriture des résultats, et à celles en court de fermeture
    ("closing"). Une boucle d'attente d'évènements déclenchée en fonction du
    statut de la disponibilité du socket ajuste ces files d'attente et distribue
    le travail au jeu de threads de travail.
    </p>

    <p>Cette nouvelle architecture, en exploitant les sockets non blocants et
    les fonctionnalités des noyaux modernes mis en valeur par
    <glossary>APR</glossary> (comme epoll de Linux), n'a plus besoin du
    <directive module="core">Mutex</directive> <code>mpm-accept</code> pour
    éviter le problème de "thundering herd".</p>

    <p>La directive <directive>AsyncRequestWorkerFactor</directive> permet de
    définir le nombre total de connexions qu'un bloc processus/thread peut
    gérer.</p>

    <section id="async-connections"><title>Connexions asynchrones</title>
        <p>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 <module>mod_status</module> montre de nouvelles
	colonnes dans la section "Async connections" :</p>
        <dl>
            <dt>Writing</dt>
            <dd>Lors de l'envoi de la réponse au client, il peut arriver que le
	    tampon d'écriture TCP soit plein si la connexion est trop lente. Si
	    cela se produit, une instruction <code>write()</code> vers le socket
	    renvoie en général <code>EWOULDBLOCK</code> ou <code>EAGAIN</code>
	    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.
            </dd>

            <dt>Keep-alive</dt>
            <dd>La gestion des connexions persistantes constitue la principale
	    amélioration par rapport au MPM Worker. Lorsqu'un thread de travail
	    a terminé l'envoi d'une réponse à un client, il peut restituer la
	    gestion du socket au thread d'écoute, qui à son tour va attendre un
	    évènement en provenance du système d'exploitation comme "le socket
	    est lisible". Si une nouvelle requête arrive en provenance du
	    client, le thread d'écoute l'attribuera au premier thread de travail
	    disponible. Inversement, si le délai <directive
	    module="core">KeepAliveTimeout</directive> 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.</dd>

            <dt>Closing</dt>
            <dd>Parfois, le MPM doit effectuer une fermeture progressive, c'est
	    à dire envoyer au client une erreur survenue précédemment alors que
	    ce dernier est en train de transmettre des données à httpd. Envoyer la réponse et
	    fermer immédiatement la connexion n'est pas une bonne solution car
	    le client (qui est encore en train d'envoyer le reste de la requête)
	    verrait sa connexion réinitialisée et ne pourrait pas lire la
	    réponse de httpd. 	    
	    La fermeture progressive est limitée dans le temps,
	    mais elle peut tout de même être assez longue, si bien qu'elle est
	    confiée à un thread de travail (y compris les procédures d'arrêt et
	    la fermeture effective du socket). A partir de la version 2.4.28,
	    c'est aussi le cas lorsque des connexions finissent par dépasser
	    leur délai d'attente (le thread d'écoute ne gère jamais les
	    connexions, si ce n'est attendre et dispatcher les évènements
	    qu'elles génèrent).</dd>
        </dl>

        <p>Ces améliorations sont disponible pour les connexions HTTP ou HTTPS.</p> 

	<p>Les états de connexions ci-dessus sont gérés par le thread d'écoute
	via des files d'attente dédiées qui, jusqu'à la version 2.4.27, étaient
	lues toutes les 100ms pour déterminer quelles connexions avaient atteint
	des limites de durées définies comme <directive
	module="mpm_common">Timeout</directive> et <directive
	module="core">KeepAliveTimeout</directive>. C'était une solution simple
	et efficace mais qui présentait un inconvénient : ces lectures
	régulières forçaient le thread d'écoute à se réveiller, souvent sans
	nécessité (alors qu'il était totalement inactif), ce qui consommait des
	ressources pour rien. A partir de la version 2.4.28, ces files d'attente
	sont entièrement gérées selon une logique basées sur les évènements, et
	ne font donc plus l'objet d'une lecture systématique. Les environnements
	aux ressources limitées, comme les serveurs embarqués, seront les plus
	grands bénéficiaires de cette amélioration.</p>

    </section>

    <section id="graceful-close"><title>Arrêt de processus en douceur et
    utilisation du scoreboard</title>
        <p>Ce MPM présentait dans le passé des limitations de montée en
	puissance qui
	provoquaient l'erreur suivante : "<strong>scoreboard is full, not at
	MaxRequestWorkers</strong>". La directive <directive
	module="mpm_common">MaxRequestWorkers</directive> permet de limiter le
	nombre de requêtes pouvant être servies simultanément à un moment donné
	ainsi que le nombre de processus autorisés (<directive
	module="mpm_common">MaxRequestWorkers</directive> / <directive
	module="mpm_common">ThreadsPerChild</directive>), 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 à <directive
	module="mpm_common">MaxRequestWorkers</directive>, 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 <directive
	module="mpm_common">ListenBacklog</directive>). 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 :</p>
        <ul>
            <li>Pendant un <a href="../stopping.html#graceful">graceful
	    restart</a>. Le processus parent demande à tous ses processus
	    enfants de terminer leur travail et de s'arrêter pendant qu'il
	    recharge la configuration et lance de nouveaux processus. Si les
	    processus existants continuent de s'exécuter pendant un certain
	    temps avant de s'arrêter, le scoreboard sera partiellement occupé
	    jusqu'à ce que les entrées correspondantes soient libérées.
            </li>
            <li>Lorsque la charge du serveur diminue suffisamment pour que httpd
	    commence à stopper certains processus (par exemple pour respecter la
	    valeur de la directive <directive
	    module="mpm_common">MaxSpareThreads</directive>). 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.
            </li>
        </ul>
        <p>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 :</p>
        <ul>
            <li>Utilisation de toutes les entrées du scoreboard dans la limite
	    de la valeur définie par <directive
	    module="mpm_common">ServerLimit</directive>. Les directives
	    <directive module="mpm_common">MaxRequestWorkers</directive> et
	    <directive module="mpm_common">ThreadsPerChild</directive>
	    permettent de limiter le nombre de processus actifs, alors que la
	    directive <directive module="mpm_common">ServerLimit</directive>
	    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 <directive
	    module="mpm_common">ServerLimit</directive> 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.
            </li>
            <li>Les processus en arrêt graceful doivent fermer leurs connexions
	    en keep-alive.</li>
            <li>Lors d'un arrêt graceful, s'il y a plus de threads de travail en
	    cours d'exécution que de connexions ouvertes pour un processus
	    donné, ces threads sont arrêtés afin de libérer les ressources plus
	    vite (ce qui peut s'avérer nécessaire pour lancer de nouveaux
	    processus).</li>
            <li>Si le scoreboard est plein, empêche d'arrêter d'autres processus
	    en mode graceful afin de réduire la charge jusqu'à ce que tous les
	    anciens processus soient arrêtés (sinon la situation empirerait lors
	    d'une remontée en charge).</li>
        </ul>
        <p>Le comportement décrit dans le dernier point est bien visible via
	<module>mod_status</module> 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.</p>
    </section>

    <section id="limitations"><title>Limitations</title>
        <p>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 <module>worker</module> 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.</p>

        <p>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.<br /> 
        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 <code>EWOULDBLOCK</code> ou
	<code>EAGAIN</code> 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.
        </p>

    </section>

    <section id="background"><title>Matériel d'arrière-plan</title>
        <p>Le modèle event a été rendu possible par l'introduction de nouvelles
	APIs dans les systèmes d'exploitation supportés :</p>
        <ul>
            <li>epoll (Linux) </li>
            <li>kqueue (BSD) </li>
            <li>event ports (Solaris) </li>
        </ul>
        <p>Avant que ces APIs soient mises à disposition, les APIs
	traditionnelles <code>select</code> et <code>poll</code> 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.</p>

        <p>Le MPM Event suppose que l'implémentation de <code>apr_pollset</code>
	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.</p>

    </section>
        
</section>

<section id="requirements"><title>Prérequis</title>
    <p>Ce MPM dépend des opérations atomiques compare-and-swap
    d'<glossary>APR</glossary> 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
    <code>--enable-nonportable-atomics=yes</code> aux arguments du
    script <program>configure</program>. Ceci permettra à APR
    d'implémenter les opérations atomiques en utilisant des instructions
    performantes indisponibles avec les processeurs plus
    anciens.</p>

    <p>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.</p>

    <ul>

      <li>Pour utiliser ce MPM sous FreeBSD, la version 5.3 ou
      supérieure de ce système est recommandée. Il est cependant
      possible d'exécuter ce MPM sous FreeBSD 5.2.1 si vous utilisez
      <code>libkse</code> (voir <code>man libmap.conf</code>).</li>

      <li>Pour NetBSD, il est recommander d'utiliser la version 2.0 ou
      supérieure.</li>

      <li>Pour Linux, un noyau 2.6 est recommandé. Il faut aussi
      s'assurer que votre version de <code>glibc</code> a été compilée
      avec le support pour EPoll.</li>

    </ul>
</section>

<directivesynopsis location="mpm_common"><name>CoreDumpDirectory</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>EnableExceptionHook</name>
</directivesynopsis>
<directivesynopsis location="mod_unixd"><name>Group</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>Listen</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>ListenBacklog</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>SendBufferSize</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>MaxRequestWorkers</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>MaxMemFree</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>MaxConnectionsPerChild</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>MaxSpareThreads</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>MinSpareThreads</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>PidFile</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>ScoreBoardFile</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>ServerLimit</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>StartServers</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>ThreadLimit</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>ThreadsPerChild</name>
</directivesynopsis>
<directivesynopsis location="mpm_common"><name>ThreadStackSize</name>
</directivesynopsis>
<directivesynopsis location="mod_unixd"><name>User</name>
</directivesynopsis>

<directivesynopsis>
<name>AsyncRequestWorkerFactor</name>
<description>Limite le nombre de connexions simultanées par thread</description>
<syntax>AsyncRequestWorkerFactor <var>facteur</var></syntax>
<default>2</default>
<contextlist><context>server config</context> </contextlist>
<compatibility>Disponible depuis la version 2.3.13</compatibility>

<usage>
    <p>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.</p>

    <p>Pour minimiser les effets de ce problème, le MPM event utilise
    deux méthodes :</p>
    <ul>
    	<li>il limite le nombre de connexions
	    simultanées par thread en fonction du nombre de processus
	    inactifs;</li>
	<li>si tous les processus sont occupés, il ferme des connexions
	permanentes, même si la limite de durée de la connexion n'a
	pas été atteinte. Ceci autorise les clients
	concernés à se reconnecter à un autre processus
	possèdant encore des threads disponibles.</li>
    </ul>

    <p>Cette directive permet de personnaliser finement la limite du
    nombre de connexions par thread. Un <strong>processus</strong> n'acceptera de
    nouvelles connexions que si le nombre actuel de connexions (sans
    compter les connexions à l'état "closing") est
    inférieur à :</p>

    <p class="indent"><strong>
        <directive module="mpm_common">ThreadsPerChild</directive> +
        (<directive>AsyncRequestWorkerFactor</directive> *
        <var>nombre de threads inactifs</var>)
    </strong></p>

    <p>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 :
    </p>


    <p class="indent"><strong>
        (<directive module="mpm_common">ThreadsPerChild</directive> +
        (<directive>AsyncRequestWorkerFactor</directive> *
        <var>number of idle workers</var>)) * 
        <directive module="mpm_common">ServerLimit</directive>
    </strong></p>

    <note><title>Exemple</title>
    <highlight language="config">

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
    
    </highlight>
    </note>

    <p>Lorsque tous les threads de travail sont inactifs, le nombre maximum
    absolu de connexions simultanées peut être calculé de manière plus simple :</p>

    <p class="indent"><strong>
        (<directive>AsyncRequestWorkerFactor</directive> + 1) *
        <directive module="mpm_common">MaxRequestWorkers</directive>
    </strong></p>

    <note><title>Exemple</title>
    <highlight language="config">
    
ThreadsPerChild = 10 
ServerLimit = 4
MaxRequestWorkers = 40
AsyncRequestWorkerFactor = 2 
    
    </highlight>

    <p>Si tous les threads de tous les processus sont inactifs, alors :</p>

    <highlight language="config">idle_workers = 10</highlight>

    <p>Nous pouvons calculer le nombre maximum absolu de connexions simultanées
    de deux manières :</p>
    
    <highlight language="config">
    
max_connections = (ThreadsPerChild + (AsyncRequestWorkerFactor * idle_workers)) * ServerLimit 
                = (10 + (2 * 10)) * 4 = 120
    
max_connections = (AsyncRequestWorkerFactor + 1) * MaxRequestWorkers 
                = (2 + 1) * 40 = 120
    
    </highlight>
    </note>

    <p>Le réglage de la directive
    <directive>AsyncRequestWorkerFactor</directive> 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
    <module>mod_status</module>.</p>

    <p>La directive <directive
    module="mpm_common">MaxRequestWorkers</directive> se nommait
    <directive>MaxClients</directive> 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.</p>

    <p>La directive <directive>AsyncRequestWorkerFactor</directive>
    accepte des valeurs d'argument de type non entier, comme "1.5".</p>

</usage>

</directivesynopsis>

</modulesynopsis>