# 2. HAProxy Architecture

> Le processus, le multithreading, la boucle d'événements, chroot, les journaux, les horloges et le modèle de proxy TCP

---

Index LLMS : [llms.txt](/fr/llms.txt)

---

<!-- Generated by scripts/generate-haproxy-docs.py from pinned upstream text. -->

HAProxy est un démon multithreadé, basé sur des événements et non bloquant. Cela signifie qu’il utilise la multiplexion d’événements pour planifier toutes ses activités, plutôt que de dépendre du système pour planifier entre plusieurs activités. La plupart du temps, il s’exécute sous la forme d’un seul processus, de sorte que la sortie de la commande « ps aux » sur un système ne répertorie qu’un seul processus « HAProxy », sauf en cas de rechargement doux en cours, auquel cas un processus ancien peut encore s’exécuter en parallèle du nouveau. Il est donc toujours facile de suivre son activité à l’aide de l’outil strace. Pour s’adapter au nombre de processeurs disponibles, HAProxy démarre, par défaut, un thread worker par processeur sur lequel il est autorisé à s’exécuter. À moins d’être configuré autrement, le trafic entrant est réparti entre tous ces threads, chacun exécutant la même boucle d’événements. Une grande attention est portée à limiter les dépendances entre threads au strict minimum, afin de tenter d’obtenir une scalabilité quasi linéaire. Cela a certaines conséquences, notamment le fait qu’une connexion donnée soit servie par un seul thread. Ainsi, pour utiliser toute la capacité de traitement disponible, il faut disposer d’au moins autant de connexions que de threads, ce qui est presque toujours le cas.

HAProxy est conçu pour s'isoler dans une prison chroot au démarrage, où il ne peut effectuer aucune opération sur le système de fichiers. Cela s'applique également aux bibliothèques sur lesquelles il dépend (par exemple : libc, libssl, etc.). L'effet immédiat est qu'un processus en cours d'exécution ne pourra pas recharger un fichier de configuration pour appliquer des modifications ; au lieu de cela, un nouveau processus sera lancé en utilisant le fichier de configuration mis à jour. Certains autres effets moins évidents sont que certains fichiers de fuseau horaire ou de résolution que libc pourrait tenter d'accéder à l'exécution ne seront pas trouvés, bien que cela devrait généralement ne pas se produire, car ces fichiers ne sont pas nécessaires après le démarrage. Une conséquence agréable de ce principe est que le processus HAProxy est entièrement sans état, et aucune opération de nettoyage n'est requise après sa suppression, aussi bien n'importe quelle méthode de suppression fonctionnera.

HAProxy n'écrit pas de fichiers journaux, mais il s'appuie sur le protocole syslog standard pour envoyer les journaux vers un serveur distant (qui se trouve souvent sur le même système).

HAProxy utilise son horloge interne pour imposer les délais d'expiration, qui est dérivée de l'heure système mais corrigée en cas de dérive imprévue. Cette correction est réalisée en limitant le temps passé en attente dans poll() pour un événement, et en mesurant le temps réellement écoulé. En pratique, il n'attend jamais plus d'une seconde. Cela explique pourquoi, lorsqu'on exécute strace sur un processus complètement inactif, des appels périodiques à poll() (ou à l'une de ses variantes), entourés de deux appels à gettimeofday(), sont observés. Ces appels sont normaux, totalement inoffensifs et si peu coûteux qu'ils sont totalement indétectables à l'échelle du système, il n'y a donc rien d'anormal à cela. Exemple :

```text
16:35:40.002320 gettimeofday({1442759740, 2605}, NULL) = 0
16:35:40.002942 epoll_wait(0, {}, 200, 1000) = 0
16:35:41.007542 gettimeofday({1442759741, 7641}, NULL) = 0
16:35:41.007998 gettimeofday({1442759741, 8114}, NULL) = 0
16:35:41.008391 epoll_wait(0, {}, 200, 1000) = 0
16:35:42.011313 gettimeofday({1442759742, 11411}, NULL) = 0
```

HAProxy est un proxy TCP, et non un routeur. Il gère les connexions établies, validées par le noyau, et non les paquets de quelque nature que ce soit ni les sockets dans d'autres états (par exemple : aucun SYN_RECV ni TIME_WAIT), bien que leur existence puisse empêcher la liaison d'un port. Il dépend du système pour accepter les connexions entrantes et initier les connexions sortantes. Un effet immédiat de cela est qu'il n'existe aucune relation entre les paquets observés des deux côtés d'une connexion redirigée, qui peuvent différer par taille, nombre, voire famille. Étant donné qu'une connexion ne peut être acceptée qu'à partir d'un socket en état LISTEN, tous les sockets sur lesquels il écoute sont nécessairement visibles à l'aide de l'outil "netstat" pour afficher les sockets d'écoute. Exemple :

```haproxy
# netstat -ltnp
```

Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State
PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:\* LISTEN 1629/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:\* LISTEN
2847/haproxy tcp 0 0 0.0.0.0:443 0.0.0.0:\* LISTEN 2847/haproxy
