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变为被动类型的,等待客户的连接请求)