【问题标题】:What can cause a “Resource temporarily unavailable” on sock connect() command什么会导致 sock connect() 命令出现“资源暂时不可用”
【发布时间】:2020-06-10 14:24:44
【问题描述】:

我正在调试一个 Python 烧瓶应用程序。该应用程序在配置有 6 个线程和 1 个进程的 uWSGI 上运行。我正在使用Flask-Executor 卸载一些较慢的任务。这些任务创建与 Flask 应用程序的连接,即同一个进程,并执行一些 HTTP GET 请求。执行程序配置为最多使用 2 个线程。此应用程序在 Ubuntu 16.04.3 LTS 上运行。

执行器中的线程每隔一段时间就会完全停止工作。该代码使用 Python requests 库来执行请求。潜在的错误消息是:

Action failed. HTTPSConnectionPool(host='somehost.com', port=443): Max retries exceeded with url: /api/get/value (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f8d75bb5860>: Failed to establish a new connection: [Errno 11] Resource temporarily unavailable',))

在执行器中运行的代码如下所示:

adapter = requests.adapters.HTTPAdapter(max_retries=3)
session  = requests.Session()
session.mount('http://somehost.com:80', adapter)
session.headers.update({'Content-Type': 'application/json'})
...
session.get(uri, params=params, headers=headers, timeout=3)

我花了很多时间试图将 Python 请求堆栈剥离到它使用的 C 套接字。我还尝试使用小型 C 和 Python 程序重现此错误。起初我认为可能是套接字没有关闭,因此我们用完了作为资源的允许套接字,但这给了我更多类似于“打开的文件太多”的消息。

抛开 Python 堆栈,什么会导致套接字 connect() 命令上出现[Errno 11] Resource temporarily unavailable?另外,如果您在使用请求时遇到了这种情况,是否有我可以传递的参数来防止这种情况发生?

我看过What can cause a “Resource temporarily unavailable” on sock send() command StackOverflow 帖子,但我是在 send() 命令上,而不是在初始 connect() 上,我怀疑这是代码挂起的地方。

【问题讨论】:

    标签: python c sockets unix linux-kernel


    【解决方案1】:

    错误信息资源暂时不可用对应错误代码EAGAIN

    connect() manpage 指出,错误 `EAGAIN 发生在以下情况:

    路由缓存中没有更多可用的本地端口或条目不足。对于 AF_INET,请参阅 /proc/sys/net/ipv4/ip_local_port_range ip(7) 的描述以获取有关如何增加本地端口数量的信息。

    当有很多连接到同一个 IP/端口组合正在使用并且找不到用于自动绑定的本地端口时,可能会发生这种情况。你可以检查

    netstat -tulpen
    

    究竟是哪些连接导致了这种情况。

    【讨论】:

    • 我知道 FreeBSD 的 connect() 也可以这样做,尽管 EAGAIN 在该操作系统上具有不同的数字 (35),因此 Linux 假设是一个安全的选择。 (如果要相信它们的手册页,NetBSD 和 Mac OSX 似乎不会这样做。)
    • 这是在 LInux 上运行的。抱歉没有说清楚。
    • 明确一点,需要打开超过 28231 个本地连接? # cat /proc/sys/net/ipv4/ip_local_port_range32768 60999。这将涵盖“不再有免费的本地端口”? “路由缓存中的条目不足”是我应该检查的另一种可能性吗?
    • @TomHuibregtse 当前的 linux 内核通常不再使用路由缓存,所以我怀疑
    • 这和新系统替换了路由缓存有关系吗?还是套接字发送/接收缓冲区?也许connect() 的手册页没有列举EAGAIN 可以涵盖的所有故障。此外,这是否与 /proc/sys/net/core/somaxconn 设置的内容有关,在我的情况下为 128?我一直在监视netstat -tulpen。我还没有看到超过 80 个连接。
    猜你喜欢
    • 2012-12-31
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    相关资源
    最近更新 更多