当前位置: 首页 > 知识库问答 >
问题:

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

郏志学
2023-05-04

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))

共有1个答案

沈冠宇
2023-05-04

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
 类似资料:
  • Supported tags and respective Dockerfile links python3.9, latest (Dockerfile) python3.8, (Dockerfile) python3.7, (Dockerfile) python3.6 (Dockerfile) python3.9-slim (Dockerfile) python3.8-slim (Dockerf

  • uvicorn 是如何实现多进程同时监听一个 socket 的?如何设置了多个工作进程,http 请求是如何在多个 worker 进程中分配的?是由谁来分配的?是操作系统把 http 请求给 master 进程,再有 master 经常转发给 worker 进程,还是操作系统直接发给 worker 进程?如果是操作系统直接发给 worker 进程,具体又是怎么给的?是操作系统轮训 worker,均

  • 问题内容: 我正在尝试在Python中的多处理库中使用队列。执行下面的代码后(打印语句起作用),但是在调用Queue上的join之后,这些进程没有退出,并且仍然存在。我如何终止其余过程? 谢谢! 问题答案: 尝试这个:

  • 我跑 fastapi 的时候,都是用 uvicorn 直接部署 但是我发现,uvicorn 的官方文档在讲部署的时候,还有 gunicorn 混搭 https://www.uvicorn.org/deployment/#gunicorn 如果 uvicorn 和 gunicorn 一起部署,还能异步吗?因为按照我的理解,gunicorn 是一个 wsgi server,而 uvicorn 是一个

  • 我写了一个fastapi应用程序。现在我正在考虑部署它,但是我似乎遇到了奇怪的意外性能问题,这似乎取决于我使用的是uvicorn还是gunicorn。特别是,如果我使用gunicorn,所有代码(甚至是标准库纯python代码)似乎都会变慢。为了进行性能调试,我编写了一个小应用程序来演示这一点: 运行Fastapi Appi与: get to的共振体始终类似于: 然而使用: 我经常得到这样的时机

  • 亚马逊EC2上的许多Django应用程序部署使用HTTP服务器NGINX和GUnicorn。 我想知道它们实际上是做什么的,为什么两者并行使用。并行运行它们的目的是什么?