nginx、uvicorn、gunicorn 这些 HTTP sever 的 socket 的 listen 队列是多大?

nginx、uvicorn、gunicorn 这些 HTTP sever 的 socket 的 listen 队列是多大?

socket server 创建监听 socket 的时候,在调用 listen 时候,可以指定一个 int 参数,表示连接请求的最大数量,也就是在连接队列中允许等待的客户端连接的数量

nginx、uvicorn、gunicorn 这些 HTTP sever 的 socket 的 listen 队列是多大?

我为什么会有和这个疑问?因为我自己写了一个简单的 TCP server 的时候,发现,客户端连接 sevrer 的时候,非常容易出现 ConnectionResetError: [Errno 54] Connection reset by peer,只要把 listen 的 int 参数修改为很大,比如 100,报错 ConnectionResetError: [Errno 54] Connection reset by peer 的概率就大大降低了

但是 nginx、uvicorn、gunicorn 这些 HTTP server 不管有多少客户端并发请求,都不会出现 ConnectionResetError: [Errno 54] Connection reset by peer

为什么?是因为 nginx、uvicorn、gunicorn 这些 HTTP sever 的 socket 的 listen 的 int 参数设置的很大很大吗?


下面是我写的测试代码:

服务端的

import socket

import sys

import time

import threading

from loguru import logger

from concurrent.futures import ThreadPoolExecutor

from concurrent.futures._base import Future

default_encoding: str = 'utf-8'

pool = ThreadPoolExecutor(

max_workers=20,

thread_name_prefix='simple-work-thread-pool'

)

def init_serversocket() -> socket.socket:

serversocket = socket.socket(

family=socket.AF_INET,

type=socket.SOCK_STREAM

)

# 获取本地主机名

host = socket.gethostname()

logger.debug(f'host {host}')

port = 6000

# 绑定端口号

serversocket.bind(('0.0.0.0', port))

# 设置最大连接数,超过后排队

serversocket.listen(5)

return serversocket

def send_response(clientsocket: socket.socket, addr: tuple, response_body: bytes) -> int:

send_len: int = clientsocket.send(response_body)

clientsocket.close()

return send_len

def start_request(clientsocket: socket.socket, addr: tuple) -> int:

try:

logger.debug(f'get message from {addr}')

request_body: bytes = clientsocket.recv(2048)

request_text: str = request_body.decode(encoding=default_encoding)

response_text: str = f'server get message: {request_text}'

response_body: bytes = response_text.encode(default_encoding)

time.sleep(1)

return send_response(clientsocket=clientsocket, addr=addr, response_body=response_body)

except Exception as error:

logger.exception(error)

def start_request_callback(future: Future) -> None:

send_len: int = future.result()

logger.debug(

f'{threading.current_thread().name}, send payload len is {send_len}')

serversocket = init_serversocket()

while True:

clientsocket, addr = serversocket.accept()

clientsocket: socket.socket

addr: tuple

future: Future = pool.submit(start_request, clientsocket, addr)

future.add_done_callback(start_request_callback)

客户端的

from base64 import encode

import socket # 客户端 发送一个数据,再接收一个数据

import json

from loguru import logger

from concurrent.futures import ThreadPoolExecutor

failture_requests = []

def send_request(index:int):

try:

# 声明socket类型,同时生成链接对象

clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

clientsocket.connect(('127.0.0.1', 6000)) # 建立一个链接,连接到本地的6969端口

payload = b'ponponon'

clientsocket.send(payload)

data = clientsocket.recv(1024)

payload = data.decode()

logger.debug(index)

clientsocket.close()

logger.debug('请求完成')

except Exception as error:

failture_requests.append(index)

logger.exception(error)

pool = ThreadPoolExecutor(max_workers=100)

for index in range(10):

pool.submit(send_request,index)

pool.shutdown(wait=True)

logger.debug(failture_requests)

logger.debug(len(failture_requests))


回答:

uvicorn 的 backlog 默认是 2048

gunicorn 的 backlog 默认是 2048

是的,这玩意叫做 backlog,很诡异的名字。(backlog(中文名“积压”、“滞后”))

nginx 的 backlog 的默认值是多少?

我问了一下 chatGPT,得到的对话结果如下:

Q:nginx 的 backlog 的默认值是多少
A:在 Nginx 中,backlog 表示监听 socket 的队列大小,即 Nginx 可以同时处理的并发连接数。默认情况下,Nginx 的 backlog 值为 511

在 Linux 中,监听 socket 队列的最大值取决于系统的参数 net.core.somaxconn,该参数的默认值通常为 128。当 backlog 值大于 net.core.somaxconn 时,实际上系统会将其截断为 net.core.somaxconn

因此,在 Nginx 中,如果需要增加 backlog 的大小,也需要将 net.core.somaxconn 参数的值相应地增加。这可以通过修改系统参数、或者在 Nginx 的配置文件中使用 worker_rlimit_nofileworker_connections 参数来实现。

Q:为什么监听 socket 的队列大小的英文名是 backlog
A:在计算机科学中,backlog(中文名“积压”、“滞后”)是一个常见的概念,指的是未能立即处理的任务或事件的数量。在网络编程中,backlog指的是未能立即处理的连接请求的数量。

在Linux中,backlog参数是指在服务端内核中维护的一个队列,用于存放连接请求,也就是连接请求的队列。当服务端使用listen系统调用打开一个socket来监听客户端连接时,backlog参数指定了在队列中允许等待的客户端连接的数量。

当服务端在处理连接请求时,如果队列已经满了,新的连接请求将会被拒绝。因此,如果backlog参数设置得太小,服务端可能无法处理所有的连接请求,导致连接被拒绝。如果设置得太大,会占用过多的内存,因此需要在服务端的负载能力和内存资源之间进行平衡。

至于为什么监听 socket 的队列大小的英文名是backlog,可能是因为在Linux内核中,这个队列是一个被称为backlog的数据结构。

Q:如何查看系统的 net.core.somaxconn
A:要查看系统的 net.core.somaxconn 参数的值,可以使用以下命令:

sysctl net.core.somaxconn

这将输出当前系统的 net.core.somaxconn 参数值。如果您想要修改该参数的值,可以使用以下命令:

sudo sysctl -w net.core.somaxconn=<new_value>

其中,<new_value> 是您想要设置的新值。请注意,这将修改系统全局参数,可能会影响其他应用程序的性能,因此请谨慎修改。如果您想要临时修改此参数,可以使用 sysctl 命令的 -w 选项,但该修改将在系统重新启动后失效。如果您想要永久修改该参数,可以将其添加到系统的配置文件中(如 /etc/sysctl.conf/etc/sysctl.d/*),以在系统启动时加载该值。


在 ubuntu22.04 下,net.core.somaxconn = 4096

╰─➤  sysctl net.core.somaxconn

net.core.somaxconn = 4096

以上是 nginx、uvicorn、gunicorn 这些 HTTP sever 的 socket 的 listen 队列是多大? 的全部内容, 来源链接: utcz.com/p/938868.html

回到顶部