Sat*_*ian 10 python multithreading operating-system process uwsgi
因此,两天前我开始为我的 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"
Run Code Online (Sandbox Code Playgroud)
当我开始时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)
Run Code Online (Sandbox Code Playgroud)
我在具有 6 核 i7 CPU 的 MacOS Catalina 上运行此程序。为什么它说detected cores: 12当我刚刚6?它说process number limit: 2784- 我真的可以设置processes = 128吗processes = 2784?在文档中,提到这个processes = 2 * cpucores指标太简单而难以遵守。理想情况下我应该考虑哪些指标?我的应用程序目前是一个 shell(即没有业务逻辑 - 现在只是在内存中获取值设置值的东西,我本质上是在构建一个模板),我们目前不期望任何数据库连接/IO 密集型操作。如何确定什么是良好的线程:进程比率?如果我的问题太基本,我深表歉意,但我对此很陌生
Raf*_*don 24
首先,核心数不一定是处理器数。在早期的计算机时代,这就像 1-1 的情况,但随着现代的改进,一个处理器可以提供多个内核。(检查此: https: //www.tomshardware.com/news/cpu-core-definition,37658.html)。因此,如果它检测到 12 个核心,您可以将其用作微积分的基础。
进程的数量意味着您的 Web 应用程序将在该服务器上运行多少个不同的并行实例。WSGI 首先创建一个主进程来协调事物。然后它会引导您的应用程序并创建它的 N 个克隆(分叉)。这些子进程是隔离的,它们不共享资源。如果一个进程由于任何原因(例如 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 微调之外,还有其他现代配置层可以帮助您应对峰值和高负载场景。
| 归档时间: |
|
| 查看次数: |
6376 次 |
| 最近记录: |