【问题标题】:Trying to figure out uWSGI thread/workers configuration试图找出 uWSGI 线程/工作者配置
【发布时间】:2021-11-22 13:43:08
【问题描述】:

所以,就在两天前,我开始为我的 python 应用程序使用 uWSGI,我试图了解我们在 .ini 文件中指定的各种参数。这是我的app.ini 文件当前的样子:

# The following article was referenced while creating this configuration
# https://www.techatbloomberg.com/blog/configuring-uwsgi-production-deployment/
[uwsgi]
strict = true                          ; Only valid uWSGI options are tolerated
master = true                          ; The master uWSGI process is necessary to gracefully re-spawn and pre-fork workers,
                                       ; consolidate logs, and manage many other features
enable-threads = true                  ; To run uWSGI in multithreading mode
vacuum = true                          ; Delete sockets during shutdown
single-interpreter = true              ; Sets only one service per worker process
die-on-term = true                     ; Shutdown when receiving SIGTERM (default is respawn)
need-app = true

;disable-logging = true                 ; By default, uWSGI has rather verbose logging. Ensure that your
;log-4xx = true                         ; application emits concise and meaningful logs. Uncomment these lines
;log-5xx = true                         ; if you want to disable logging

cheaper-algo = busyness
processes = 128                      ; Maximum number of workers allowed
cheaper = 1                          ; Minimum number of workers allowed - default 1
cheaper-initial = 2                  ; Workers created at startup
cheaper-overload = 60                ; Will check busyness every 60 seconds.
cheaper-step = 3                     ; How many workers to spawn at a time

auto-procname = true                 ; Identify the workers
procname-prefix = "rhs-svc "         ; Note the space. uWSGI logs will be prefixed with "rhs-svc"

当我开始uWSGI - 这是我看到的:

[uWSGI] getting INI configuration from app.ini
*** Starting uWSGI 2.0.19.1 (64bit) on [Thu Sep 30 10:49:45 2021] ***
compiled with version: Apple LLVM 12.0.0 (clang-1200.0.32.29) on 29 September 2021 23:55:27
os: Darwin-19.6.0 Darwin Kernel Version 19.6.0: Thu Sep 16 20:58:47 PDT 2021; root:xnu-6153.141.40.1~1/RELEASE_X86_64
nodename: sth-sth-sth
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 12
current working directory: /Users/sth.sth/My-Microservice
detected binary path: /Users/sth.sth/My-Microservice/venv/bin/uwsgi
your processes number limit is 2784
your memory page size is 4096 bytes
detected max file descriptor number: 10240
lock engine: OSX spinlocks
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :9000 fd 4
[busyness] settings: min=25%, max=50%, overload=60, multiplier=10, respawn penalty=2
uwsgi socket 0 bound to TCP address 127.0.0.1:57164 (port auto-assigned) fd 3
Python version: 3.9.6 (default, Jun 29 2021, 06:20:32)  [Clang 12.0.0 (clang-1200.0.32.29)]
Python main interpreter initialized at 0x7fd32b905bf0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 9403584 bytes (9183 KB) for 128 cores
*** Operational MODE: preforking ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fd32b905bf0 pid: 78422 (default app)
spawned uWSGI master process (pid: 78422)
spawned uWSGI worker 1 (pid: 78423, cores: 1)
spawned uWSGI worker 2 (pid: 78424, cores: 1)
spawned uWSGI http 1 (pid: 78425)

我在带有 6 核 i7 CPU 的 MacOS Catalina 上运行它。为什么我只有6 时会显示detected cores: 12?它说process number limit: 2784 - 我真的可以将processes = 128 设置为processes = 2784 吗? In the docs,有人提到processes = 2 * cpucores 是一个过于简单的指标,无法坚持。理想情况下我应该考虑哪些指标?我的应用程序目前是一个外壳(即没有业务逻辑——现在只是在内存中获取值设置值的东西,我实际上是在构建一个模板),我们现在不期望任何数据库连接/IO 密集型操作.如何确定什么是好的线程:进程比率?如果我的问题太基本,我深表歉意,但我对此很陌生

【问题讨论】:

    标签: python multithreading process operating-system uwsgi


    【解决方案1】:

    内核与处理器

    首先,核心数不一定是处理器数。在早期的计算机时代,这就像 1-1,但随着现代改进,一个处理器可以提供多个内核。 (检查:https://www.tomshardware.com/news/cpu-core-definition,37658.html)。因此,如果它检测到 12 个核心,您可以将其用作您的微积分基础。

    WSGI 进程

    进程数表示您的 Web 应用程序的不同并行实例将在该服务器中运行的数量。 WSGI 首先创建一个主进程来协调事物。然后它引导您的应用程序并创建它的 N 个克隆(fork)。这些子分支进程是隔离的,它们不共享资源。如果一个进程由于任何原因(例如 I/O 问题)变得不健康,它可以终止甚至被主进程自愿杀死,而其余的克隆继续工作,因此您的应用程序仍然正常运行。当一个进程被终止/杀死时,主进程可以创建另一个新的克隆来替换它(重新生成)。

    可以将进程数设置为可用内核的比率。但是增加太多并没有什么好处。所以,你绝对不应该把它设置到极限(2784)。请记住,操作系统将在所有进程之间循环,让每个进程都有机会处理一些指令。因此,如果它提供 12 个内核并且您创建了大约 1000 个不同的进程,那么您只是给系统施加了压力,最终您将获得相同的吞吐量(或者甚至更差的吞吐量,因为有太多的混乱)。

    进程内的线程数

    然后我们继续讨论线程数。为了简单起见,我们只说线程数是指每个子进程可以处理的并行请求数。当一个线程正在等待数据库响应以响应请求时,另一个线程可能正在执行其他操作来响应另一个请求。

    你可能会说:如果我已经有多个进程,为什么还需要多个线程?

    进程是昂贵的东西,但线程只是您可以并行处理进程可以处理的工作负载的方式。想象一个进程是一个咖啡店,线程是你里面的服务员的数量。您可以在城市各处分布 10 个不同的咖啡店单位。如果其中一个关闭,那么客户可以去的其他地方还有另外 9 个。但是每家商店都需要一定数量的服务员才能以最好的方式为人们服务。

    如何正确设置这些数字

    如果您只设置一个具有 100 个线程的进程,这意味着 100 是您的并发限制。如果在某个时候对您的应用程序有 101 个并发请求,那么最后一个请求将不得不等待第一个完成的 100 个请求中的一个。那时您开始为某些用户获得越来越多的响应时间。请求排队的次数越多,情况就越糟糕(排队论)。

    此外,由于您只有一个进程,因此如果它崩溃,所有这 100 个请求都会失败并出现服务器错误 (500)。因此,拥有更多进程更为明智,假设 4 个进程每个处理 25 个线程。您仍然有 100 个并发限制,但您的应用程序更具弹性。

    您需要了解应用程序的预期负载,以便正确调整这些数字。当您有像数据库这样的外部集成时,您还必须考虑它的局限性。假设一个 PostgreSQL 服务器可以同时处理 100 个连接。如果你有 10 个 WSGI 进程,每个进程有 40 个线程(连接池大小也是 40),那么你有可能用 400 个连接对数据库施加压力,然后你就会遇到很大的问题,但这不是你的情况!

    因此,只需使用建议的进程数 (12 * 2 = 24) 并根据需要设置尽可能多的线程来提供所需的特定并发级别。

    如果您不知道预期的负载,我建议您进行某种性能测试,以模拟对您的应用程序的请求,然后您可以试验不同的负载和设置并检查其副作用。

    额外:容器

    如果您在容器编排平台(如 Kubernetes)中运行您的应用程序,那么您可能有多个平衡的容器服务于同一个应用程序。您甚至可以使其动态化,以便在内存或处理超过阈值时增加容​​器的数量。这意味着除了针对单个服务器的所有这些 WSGI 微调之外,还有其他现代配置层可以帮助您应对高峰和高负载情况。

    【讨论】:

    • 这实际上非常有用。你的例子实际上让我更清楚地了解我到目前为止的任何理解。我现在对自己的参数更有信心了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 2013-03-15
    • 1970-01-01
    • 2013-06-05
    • 2015-07-01
    相关资源
    最近更新 更多