web-dev-qa-db-fra.com

Plusieurs processus en écoute sur le même port; comment est-ce possible?

Plusieurs processus écoutent sur le même port. Mais pour autant que je sache, un seul processus peut écouter sur un port. Est-il possible (comment?) Que plusieurs processus puissent écouter sur le même port?

$ Sudo lsof -n -i :80 | grep LISTEN
haproxy 2039 root    4u  IPv4  12874      0t0  TCP *:http (LISTEN)
haproxy 2042 root    4u  IPv4  12898      0t0  TCP *:http (LISTEN)
haproxy 2045 root    4u  IPv4  12923      0t0  TCP *:http (LISTEN)

pstree sortie:

init
  ├─acpid -c /etc/acpi/events -s /var/run/acpid.socket
  ├─atd
  ├─cron
  ├─dbus-daemon --system --fork
  ├─dhclient -1 -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases eth0 
  ├─docker -d
  │   └─6*[{docker}]
  ├─getty -8 38400 tty4
  ├─getty -8 38400 tty5
  ├─getty -8 38400 tty2
  ├─getty -8 38400 tty3
  ├─getty -8 38400 tty6
  ├─getty -8 38400 tty1
  ├─getty -8 38400 ttyS0
  ├─haproxy -f /etc/haproxy/haproxy.cfg
  ├─haproxy -f /etc/haproxy/haproxy.cfg
  ├─haproxy -f /etc/haproxy/haproxy.cfg

configuration haproxy:

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    user ubuntu
    group ubuntu
    daemon 

defaults
    log global
    mode    http
    option  httplog
    option  dontlognull
        contimeout 5000
        clitimeout 50000
        srvtimeout 50000

listen appname 0.0.0.0:80
    mode http
    stats enable
    stats uri /haproxy?stats
    balance roundrobin
    option httpclose
    option forwardfor
    server lamp1 172.31.20.0:81 check
    server lamp2 172.31.20.1:81 check
9
Kundan

C'est possible. L'objectif est de traiter plusieurs connexions entrantes en parallèle. Plusieurs instances haproxy peuvent utiliser des cœurs de processeur distincts et fonctionner (semi-) indépendamment. La connexion entrante sera transmise à inactif haproxy (si disponible) au lieu d’être mise en file d’attente à occupée.

Je suppose haproxy utilise SO_REUSEPORT. man 7 socket explique cette option comme suit:

SO_REUSEPORT (depuis Linux 3.9)

Permet à plusieurs sockets AF_INET ou AF_INET6 d'être liés à une adresse de socket identique. Cette option doit être définie sur chaque prise (y compris la première prise) avant d'appeler bind(2) sur la prise. Pour empêcher le piratage de port, tous les processus liés à la même adresse doivent avoir le même UID effectif. Cette option peut être utilisée avec TCP et les sockets UDP.

Pour TCP sockets, cette option permet d'améliorer la distribution de charge accept(2) dans un serveur multithread en utilisant un socket d'écouteur distinct pour chaque thread. Cela améliore la répartition de la charge par rapport aux techniques traditionnelles, telles que l’utilisation d’un seul thread accept(2)ing qui distribue les connexions ou la présence de plusieurs threads en concurrence avec accept(2) à partir du même socket.

Vérifiez également SO_ATTACH_REUSEPORT_CBPF et SO_ATTACH_REUSEPORT_EBPF à cet endroit.


Edit: J'ai trouvé cet article (daté du 3 mai 2017); il semble soutenir ma supposition:

Entre temps, une nouvelle et bien meilleure implémentation de SO_REUSEPORT a été apportée au noyau Linux 3.9, permettant à la charge d'être répartie de manière intelligente sur plusieurs sockets. HAProxy pourrait immédiatement bénéficier de cette nouvelle amélioration.

Mais c'est venu avec un problème [...]

Ne vous inquiétez pas du problème. L'article décrit des solutions de contournement et une solution. Vous pouvez trouver cela intéressant si vous aimez ce genre de choses.

7
Kamil Maciorowski