Несколько процессов прослушивают один и тот же порт; как это возможно?

Несколько процессов прослушивают один и тот же порт. Но, насколько я знаю, только один процесс может прослушивать порт. Возможно ли (как?), Что несколько процессов могут прослушивать один и тот же порт?

$ 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 выход:

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

Конфигурация 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

1 ответ

Решение

Это возможно. Цель состоит в том, чтобы обрабатывать несколько входящих соединений параллельно. множественный haproxy экземпляры могут использовать отдельные ядра ЦП и работать (полу) независимо. Входящее соединение будет передано в режим ожидания haproxy (если доступно) вместо того, чтобы ставиться в очередь на занятого.

Похоже haproxy использования SO_REUSEPORT, man 7 socket объясняет эту опцию так:

SO_REUSEPORT (начиная с Linux 3.9)

Разрешает несколько AF_INET или же AF_INET6 сокеты должны быть связаны с идентичным адресом сокета. Эта опция должна быть установлена ​​на каждом сокете (включая первый сокет) до вызова bind(2) на розетке. Чтобы предотвратить перехват портов, все процессы, привязанные к одному и тому же адресу, должны иметь один и тот же эффективный UID. Эта опция может использоваться с сокетами TCP и UDP.

Для сокетов TCP эта опция позволяет accept(2) Распределение нагрузки в многопоточном сервере должно быть улучшено за счет использования отдельного сокета слушателя для каждого потока. Это обеспечивает улучшенное распределение нагрузки по сравнению с традиционными методами, такими как использование одного accept(2) -ing поток, который распределяет соединения, или имеет несколько потоков, которые конкурируют с accept(2) из той же розетки.

Также проверьте SO_ATTACH_REUSEPORT_CBPF а также SO_ATTACH_REUSEPORT_EBPF там.


Изменить: я нашел эту статью (от 3 мая 2017 года); кажется, поддерживает мое предположение:

А пока новое и намного лучше SO_REUSEPORT Реализация была перенесена в ядро ​​Linux 3.9, что позволило разумно распределить нагрузку по нескольким сокетам. HAProxy может немедленно извлечь выгоду из этого нового улучшения.

Но это пришло с проблемой [...]

Не беспокойся о проблеме. В статье описаны обходные пути и решение. Вы можете найти это интересным, если вам нравятся такие вещи.

Другие вопросы по тегам