<-
Apache > Serveur HTTP > Documentation > Version 2.2 > Serveurs virtuels

Détails sur le fonctionnement des serveurs virtuels

Langues Disponibles:  en  |  fr  |  ko  |  tr 

Le code gérant les serveurs virtuels a été réécrit à partir de zéro dans Apache 1.3. Ce document vise à expliquer dans le détail comment Apache procède lors du choix de l'utilisation d'un serveur virtuel en fonction d'une requête reçue. L'apparition de la directive NameVirtualHost a rendu beaucoup plus facile et plus sûre la configuration des serveurs virtuels par rapport aux versions précédant la 1.3.

Si vous voulez juste que ça marche sans en comprendre le fonctionnement, voici quelques exemples.

top

Interprétation des fichiers de configuration

Un serveur principal (main_server) contient toutes les définitions qui apparaissent en dehors des sections <VirtualHost>. Les serveurs virtuels, aussi appelés vhosts (pour virtual hosts), sont définis par les sections <VirtualHost>.

Les directives ServerName et ServerPath peuvent être placées n'importe où dans le cadre de définition d'un serveur. Cependant, chaque fois que l'une d'elles est lue, elle écrase ses instances précédentes (dans le contexte du même serveur).

Le serveur principal n'a pas de valeur par défaut pour ServerPath ni pour ServerAlias. La valeur par défaut de ServerName est déduite à partir de l'adresses IP du serveur.

Les numéros de port spécifiés par la directive VirtualHost n'ont rien à voir avec les ports sur lesquels Apache va se mettre en écoute. Ils permettent seulement de déterminer quel VirtualHost devra être sélectionné pour traiter la requête.

Chaque adresse incluse dans une directive VirtualHost peut disposer d'un port optionnel. Si le port n'est pas précisé, il pourra prendre n'importe quelle valeur. Le port particulier * représente un joker qui correspond à tous les ports. L'ensemble des adresses (y compris les résultats multiples A issus des requêtes DNS) est appelé jeu d'adresses du serveur virtuel.

À moins qu'une directive NameVirtualHost ne soit utilisée pour la paire adresse IP exacte/port dans la directive VirtualHost, Apache sélectionne le serveur virtuel qui correspond le mieux en se basant sur l'adresse IP (ou une adresse quelconque) et le numéro de port. Si plusieurs serveurs virtuels correspondent sans pouvoir être départagés, c'est le premier qui apparaît dans le fichier de configuration qui sera sélectionné.

Si vous souhaitez qu'Apache affine ses critères de sélection en faisant entrer en jeu l'en-tête HTTP Host fourni par le client, la directive NameVirtualHost doit apparaître avec la paire adresse IP exacte (ou adresse quelconque)/port utilisée dans le jeu de directives VirtualHost correspondant.

La sélection du serveur virtuel en fonction du nom n'intervient qu'après la sélection d'un serveur virtuel à base d'adresse IP unique, et ne prend en compte que l'ensemble des serveurs virtuels qui possèdent la même paire adresse IP/port.

On peut utiliser des nom d'hôtes à la place d'adresses IP dans la définition des serveurs virtuels, mais ils seront résolus en adresses IP au démarrage du serveur et ceci n'est pas recommandé.

On peut utiliser plusieurs directives NameVirtualHost pour un groupe de directives VirtualHost, mais seule une directive NameVirtualHost doit être utilisée pour chaque couple IP:port donné.

L'ordre d'apparition des directives NameVirtualHost et VirtualHost est sans importance, ce qui fait que les deux exemples suivants ont des effets identiques (seul l'ordre des directives VirtualHost pour un jeu d'adresses est important, voir ci-dessous) :

NameVirtualHost 111.22.33.44
<VirtualHost 111.22.33.44>
# serveur A
...
</VirtualHost>
<VirtualHost 111.22.33.44>
# serveur B
...
</VirtualHost>

NameVirtualHost 111.22.33.55
<VirtualHost 111.22.33.55>
# serveur C
...
</VirtualHost>
<VirtualHost 111.22.33.55>
# serveur D
...
</VirtualHost>

<VirtualHost 111.22.33.44>
# serveur A
</VirtualHost>
<VirtualHost 111.22.33.55>
# serveur C
...
</VirtualHost>
<VirtualHost 111.22.33.44>
# serveur B
...
</VirtualHost>
<VirtualHost 111.22.33.55>
# serveur D
...
</VirtualHost>

NameVirtualHost 111.22.33.44
NameVirtualHost 111.22.33.55

(Il est conseillé d'adopter le choix de gauche pour faciliter la lisibilité des fichiers de configuration.)

Pendant la phase d'initialisation, une liste de chaque adresse IP est générée et introduite dans une table de 'hash'. Si une adresse IP est utilisée dans une directive NameVirtualHost, cette liste contient les noms des serveurs virtuels pour cette adresse. Si aucun serveur virtuel n'est défini pour cette adresse, la directive NameVirtualHost est ignorée et un message est envoyé au journal d'erreurs. Quand un serveur virtuel par IP est utilisé, la table de 'hash' reste vide.

La fonction de 'hash' étant rapide, le temps d'exécution d'un 'hash' sur une adresse IP lors d'une requête est minimale et quasiment imperceptible. De plus, la table est optimisée pour les adresses IP dont le dernier octet est le seul à changer.

Pour chaque serveur virtuel, diverses valeurs sont initialisées par défaut. En particulier :

  1. Dans le cas où un serveur virtuel ne contient pas de directives ServerAdmin, Timeout, KeepAliveTimeout, KeepAlive, MaxKeepAliveRequests, ReceiveBufferSize, ou SendBufferSize, alors la valeur de chacun de ces paramètres est héritée de celle du serveur principal. (C'est à dire, héritée de la valeur finale après lecture de la configuration du serveur principal.)
  2. Les permissions par défaut sur les répertoires de chaque serveur virtuel sont assemblées avec celles du serveur principal. Elles concernent également toutes les informations de configuration par répertoire pour tous les modules.
  3. Les configurations par serveur pour chaque module sont assemblées à partir de celles du serveur principal.

L'essentiel des valeurs de configuration des serveurs virtuels provient de valeurs par défaut issues du serveur principal. Mais la position dans le fichier de configuration des directives du serveur principal n'a pas d'importance -- l'ensemble de la configuration du serveur principal est lu avant que ces valeurs par défaut soient appliquées aux serveur virtuels. Ainsi, même si la définition d'une valeur apparaît après celle d'un serveur virtuel, cette valeur peut affecter la definition du serveur virtuel.

Dans le cas où le serveur principal n'a pas de ServerName à ce stade, le nom de la machine sur laquelle tourne le programme httpd est utilisé à sa place. Nous appellerons jeu d'adresses du serveur principal les adresses IP renvoyées par une résolution DNS sur le ServerName du serveur principal.

Pour tous les champs ServerName non définis, dans le cas d'une configuration en serveur virtuel par nom, la valeur adoptée par défaut est la première adresse donnée dans la section VirtualHost qui définit le serveur virtuel.

Si un serveur virtuel contient la valeur magique _default_, il fonctionne sur le même ServerName que le serveur principal.

top

Choix du serveur virtuel

À la réception d'une requête, le serveur procède comme suit pour déterminer quel serveur virtuel utiliser :

Vérification dans la table de hash

Après que le client se soit connecté, l'adresse IP à laquelle le client s'est connecté est recherchée dans la table de hash IP interne.

Si la résolution de l'adresse IP n'aboutit pas (adresse IP non trouvée), la requête est servie par le serveur virtuel _default_ s'il est défini pour le port correspondant à la requête. Sinon, elle est servie par le serveur principal.

Si l'adresse IP n'est pas trouvée dans la table de hash, la recherche du numéro de port peut aussi se terminer par une correspondance à un NameVirtualHost * qui est géré ensuite comme les autres serveurs virtuels par noms.

Si une liste est bien trouvée dans la table pour l'adresse IP recherchée, l'étape suivante est de déterminer s'il s'agit d'un serveur virtuel par nom ou par IP.

Serveur virtuel par IP

Si l'entrée trouvée dispose d'une liste de noms vide, c'est qu'il s'agit d'un serveur virtuel par IP, et aucun autre choix n'est plus à faire ; la requête est servie par ce serveur virtuel.

Serveur virtuel par nom

Si l'entrée trouvée correspond à un serveur virtuel par nom, la liste de noms contient au moins une structure de serveurs virtuels. Les serveurs virtuels se présentent dans cette liste dans le même ordre que la lecture des directives VirtualHost dans le fichier de configuration.

Le premier serveur virtuel de cette liste (donc, le premier serveur virtuel du fichier de configuration attribué à l'adresse IP spécifiée) se voit attribuer la plus grande priorité, ce qui signifie que c'est lui qui traite les requêtes présentant un nom de serveur invalide ou ne présentant pas de champ Host: dans l'en-tête.

Si un champ Host: est transmis dans l'en-tête de la requête, son occurrence est recherchée dans la liste et le premier serveur virtuel qui présente un ServerName ou un ServerAlias correspondant est choisi pour servir la requête. Il est possible que le champ Host: contienne un numéro de port, mais Apache utilise toujours le port sur lequel il a effectivement reçu la requête.

La liste complète des noms dans la section VirtualHost sont traités comme un ServerAlias sans caractères génériques (mais ne sont pas écrasés par une directive ServerAlias).

Dans le cas où le client a envoyé une requête en HTTP/1.0 sans champ d'en-tête Host:, il est impossible de déterminer le serveur auquel le client veut se connecter ; l'URI de la requête est recherché dans tous les ServerPath existants. Le premier chemin trouvé est utilisé et la requête est servie par le serveur virtuel correspondant.

Si aucun serveur virtuel n'est trouvé, la requête est servie par le premier serveur virtuel qui écoute sur le port demandé et qui est sur la liste associée à l'adresse IP vers laquelle la requête a été envoyée (comme déjà précisé ci-avant).

Connexions persistantes

La recherche par adresse IP décrite ci-avant n'est faite qu'une fois pour chaque session TCP/IP, alors que la recherche par nom est réalisée pour chaque requête au cours d'une connexion persistante (KeepAlive). En d'autres termes, il est possible pour un client de faire des requêtes sur différents serveurs virtuels par nom, au cours d'une unique connexion persistante.

URI absolu

Au cas où l'URI de la requête est absolu, et que son nom de serveur et son port correspondent au serveur principal (ou l'un des serveurs virtuels configurés), et qu'ils correspondent à l'adresse et au port de la requête, alors l'URI est amputé de son préfixe protocole/nom de serveur/port et traité par le serveur correspondant (principal ou virtuel). Si cette correspondance n'existe pas, l'URI reste inchangé et la requête est considérée comme une requête d'un serveur mandataire (proxy).

Observations

top

Trucs et astuces

En plus des points évoqués sur la page des problèmes liés au DNS, voici quelques points intéressants :

Langues Disponibles:  en  |  fr  |  ko  |  tr 

top

Commentaires

Notice:
This is not a Q&A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our mailing lists.