【问题标题】:Can SO_REUSEPORT be used on Unix domain sockets?SO_REUSEPORT 可以在 Unix 域套接字上使用吗?
【发布时间】:2014-07-07 16:28:05
【问题描述】:

Linux 内核 >= 3.9 允许通过设置 SO_REUSEPORT: http://lwn.net/Articles/542629/ 在内核负载平衡的进程之间共享套接字

这如何用于AF_UNIX 类型的套接字?

看来,它只适用于 TCP,不适用于 Unix 域套接字。

这是一个 Python 测试程序:

import os
import socket

if not hasattr(socket, 'SO_REUSEPORT'):
   socket.SO_REUSEPORT = 15

if True:
   # using TCP sockets
   # works. test with: "echo data | nc localhost 8888"
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
   s.bind(('', 8888))
else:
   # using Unix domain sockets
   # does NOT work. test with: "echo data | nc -U /tmp/socket1"
   s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
   s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
   try:
      os.unlink("/tmp/socket1")
   except:
      pass
   s.bind("/tmp/socket1")

s.listen(1)
while True:
   conn, addr = s.accept()
   print('Connected to {}'.format(os.getpid()))
   data = conn.recv(1024)
   conn.send(data)
   conn.close()

启动 2 个实例,并通过多次运行以下命令进行测试:

  • echo data | nc localhost 8888 用于 TCP
  • echo data | nc -U /tmp/socket1 用于 Unix 域套接字

使用 TCP 时,传入的客户端将平衡到两个服务器。使用 Unix 域套接字,传入的客户端都连接到最后启动的服务器。

【问题讨论】:

  • 你引用的文章的第一句话:One of the features merged in the 3.9 development cycle was TCP and UDP support for the SO_REUSEPORT socket option。它似乎只支持 TCP 和 UDP。
  • 我没有确切的答案,但看起来内核无法对 UNIX 套接字进行负载平衡。这有很多有用的信息:stackoverflow.com/questions/14388706/…
  • @AlexShkop 谢谢! FWIW,我可以在 UDS 上设置选项,这将允许多个进程打开同一个 UDS(监听)。如果未设置该选项,则不允许这样做。但是,它不会进行负载平衡。我正在寻找一个支持观察到的行为或展示如何进行 LB 平衡共享 UDS 的权威答案。

标签: python linux sockets networking tcp


【解决方案1】:

一个小补丁,增加了对 UNIX 套接字 was posted 上的 SO_REUSEPORT 的支持,但已被拒绝。然而,这个补丁并没有在多个套接字上实现负载平衡,它只会导致bind() 在套接字文件已经存在的情况下不会失败。

此用例被视为

从用户的角度来看一个非常奇怪的极端案例

因此,仍然有可能接受通过SO_REUSEPORT 为 UNIX 套接字实现负载平衡的不同补丁。

【讨论】:

  • 感谢指点!我仍然认为该用例是有效且重要的:拥有基于已建立的用户 API(UDS 上的套接字)的安全、高性能、低开销的 IPC 机制。当然,现在还有其他 IPC 机制(netmap、DDPK)......但与几十年前的 Posix 套接字 API 和 UDS 相比,这些机制通常更复杂。
【解决方案2】:

这里记录了这个特定的内核补丁:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c617f398edd4db2b8567a28e899a88f8f574798d

从补丁文件列表中可以看出,补丁只影响了net/ipv4net/ipv6 套接字。 Unix 域套接字在net/unix 中实现。所以,答案是:不,SO_REUSEPORT 不适用于 AF_UNIX 类型的套接字。

【讨论】:

  • 好的。谢谢!这是一个权威的答案——尽管它是否定的=(
  • 很抱歉让您失望了。但也许你可以切换到普通插座?
  • 答案似乎仍然是最新的。我仍然会欣赏权威更新:)
猜你喜欢
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 2010-12-06
  • 2014-07-24
  • 1970-01-01
  • 2014-11-12
相关资源
最近更新 更多