多个进程监听同一个端口;这怎么可能?

Kun*_*dan 13 networking linux port ubuntu haproxy

多个进程正在侦听同一个端口。但据我所知,只有一个进程可以监听一个端口。是否有可能(如何?)多个进程可以在同一个端口上侦听?

$ 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)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Kam*_*ski 13

有可能的。目标是并行处理多个传入连接。多个haproxy实例可以使用单独的 CPU 内核并(半)独立地工作。传入的连接将被传递到空闲haproxy(如果可用)而不是排队到忙碌的连接。

我猜 haproxy使用SO_REUSEPORT. man 7 socket像这样解释这个选项:

SO_REUSEPORT (从 Linux 3.9 开始)

允许将多个AF_INETAF_INET6套接字绑定到相同的套接字地址。在调用套接字之前,必须在每个套接字(包括第一个套接字)上设置此选项bind(2)。为了防止端口劫持,所有绑定到同一地址的进程必须具有相同的有效 UID。此选项可用于 TCP 和 UDP 套接字。

对于 TCP 套接字,此选项允许accept(2)通过为每个线程使用不同的侦听器套接字来改进多线程服务器中的负载分布。与传统技术相比,这提供了改进的负载分配,例如使用accept(2)分配连接的单个线程,或具有accept(2)从同一套接字竞争的多个线程。

也检查SO_ATTACH_REUSEPORT_CBPFSO_ATTACH_REUSEPORT_EBPF那里。


编辑:我找到了这篇文章(日期为 2017 年 5 月 3 日);它似乎支持我的猜测:

与此同时,SO_REUSEPORTLinux 内核 3.9 引入了一个新的更好的实现,允许负载智能地分布在多个套接字上。HAProxy 可以立即从这项新改进中受益。

但它带来了一个问题 [...]

不要担心这个问题。本文介绍了变通方法和解决方案。如果你喜欢这种东西,你可能会发现它很有趣。