Python socket.listen(...)

Posted

技术标签:

【中文标题】Python socket.listen(...)【英文标题】:Python sock.listen(...) 【发布时间】:2011-01-27 12:25:49 【问题描述】:

我在 python 文档中看到的所有关于sock.listen(5) 的示例都建议我应该将最大积压数设置为5。这给我的应用程序带来了问题,因为我期待一些非常高的容量(许多并发连接)。我将它设置为 200 并且在我的系统上没有发现任何问题,但想知道在它引起问题之前我可以将它设置多高..

有人知道吗?

编辑:这是我的 accept() 循环。

while True:    
    try:
        self.q.put(sock.accept())
    except KeyboardInterrupt:
        break
    except Exception, e:
        self.log("ERR %s" % e)

【问题讨论】:

这里有一些信息:***.com/questions/114874/… 我刚刚检查了socket.SOMAXCONN 的值并注意到它的128,这可以解释为什么将值设置为200 对ab -c 200 不起作用(它只适用于120 的并发)。 使用 self.q.put_nowait() 代替。 @Heath Hunnicutt:这没什么用,因为队列没有限制,因此它永远不会阻塞。 (另外,到目前为止,我还没有看到队列长度超过 100) 你介意逗我一下,看看 x = sock.accept() \ x.close() 是否为你解决了ab阻塞的问题?特别是,您所描述的您无法在 SOMAXCONN 之上维护多个连接不应该是您调用 accept() 后的 Linux 行为,这将是(默认)1024 的每个进程打开文件句柄限制。跨度> 【参考方案1】:

您不需要将listen()的参数调整为大于5的数字。

该参数控制允许有多少非accept()-ed 连接处于未完成状态。 listen() 参数与并发连接的套接字数无关,仅与未被进程accept()-ed 的并发连接数有关。

如果将参数调整为listen() 对您的代码有影响,则表示每次调用accept() 之间会出现太多延迟。然后,您需要更改 accept() 循环,以减少开销。

在你的情况下,我猜self.q 是一个python queue,在这种情况下你可能想调用self.q.put_nowait() 以避免任何阻塞accept() 循环的可能性在这次电话会议上。

【讨论】:

如果这是真的那么ab 有问题,因为增加backlog 的大小解决了我的问题。 @Heath,如果每秒有很多连接是可能的。大量积压将使您能够更好地处理瞬态负载 @Ian:什么是“ab”?正如我在回答中所写的那样,如果增加积压可以解决您的问题,这意味着您调用 accept() 的频率不足以跟上传入的连接。你的 accept() 代码是如何工作的? @gnibbler,任何短暂的峰值都将由客户端重试处理。正如 TCP 设计的那样,任何慢性过载都将通过连接超时来处理。使用 SOMAXCONN 可能是可取的,但遇到此问题表明服务器实现的其他地方存在缺陷,不应将其掩盖为 OP 的劣势。 @Heath,5 似乎有点低。也许它是Win98时代的遗物。现在 linux 中的默认值是 128。我想知道是否有办法监控繁忙服务器上积压的高水位标记。【参考方案2】:

医生这么说

socket.listen(backlog) 收听 与套接字建立的连接。这 backlog 参数指定最大值 排队的连接数和 应至少为 1;最大值 值取决于系统(通常为 5)。

显然系统值在您的系统上大于 5。我不明白为什么将其设置为更大的数字会是一个问题。可能会为每个排队的连接保留一些内存。

我的 linux 手册页有这样的说法

如果 backlog 参数大于 /proc/sys/net/core/somaxconn,然后它 被默默地截断为该值; 此中的默认值 文件为 128。在 2.4.25 之前的内核中,此限制是硬编码值 SOMAXCONN,值为 128。

【讨论】:

刚刚在 osx 上检查过,socket.SOMAXCONN 也是 128.. 有点糟糕,意味着当前待处理连接的最大数量是 128.. 当然,这很多,但考虑到短/快的性质这些请求..我希望有更多的并发性。 不,内核只会在 SOMAXCONN 之后无法 ACK 连接请求。这是期望的行为;如果您确实持有超过 128 个排队的连接请求,那么您是 a) 处理它们的时间太长或 b) 需要一个重量级的分布式服务器或 c) 遭受 DDoS 攻击。 @Ian,在 Linux 上你可以echo 256 > /proc/sys/net/core/somaxconn。然而,在增加这个数字之前,你应该努力让你的处理程序更快 嗯,好吧,我想 128 应该是最大值,请注意,我不确定如何使 sock.accept() 循环运行得更快.. 如果我创建几个线程会怎样接受传入的连接?【参考方案3】:

从 Python 3.5 开始,可以选择将 backlog 作为默认参数传递,因此您可以将其留空:

如果未指定,则选择默认的合理值。在 3.5 版更改:积压参数现在是可选的。

https://docs.python.org/3/library/socket.html#socket.socket.listen

【讨论】:

以上是关于Python socket.listen(...)的主要内容,如果未能解决你的问题,请参考以下文章

[python]socket.listen(backlog)中的backlog含义

C语言 socket listen()函数(socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求)

如何确定socket listen() backlog 参数的值?

socket listen参数中的backlog

在python中收听无限数量的套接字

socket通信的流程