6

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

$ 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 ответ1

5

Это возможно. Цель состоит в том, чтобы обрабатывать несколько входящих соединений параллельно. Несколько экземпляров 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) который распределяет соединения, или наличие нескольких потоков, которые конкурируют за accept(2) из одного и того же сокета.

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


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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .