草庐IT

Python、WSGI、多处理和共享数据

coder 2023-05-25 原文

我对 mod_wsgi 的多处理功能以及将在具有多处理能力的 WSGI 服务器上执行的 WSGI 应用程序的一般设计有点困惑。

考虑以下指令:

WSGIDaemonProcess example processes=5 threads=1

如果我理解正确,mod_wsgi 将生成 5 个 Python(例如 CPython)进程,并且这些进程中的任何一个都可以接收来自用户的请求。

文档说:

Where shared data needs to be visible to all application instances, regardless of which child process they execute in, and changes made to the data by one application are immediately available to another, including any executing in another child process, an external data store such as a database or shared memory must be used. Global variables in normal Python modules cannot be used for this purpose.

但是在这种情况下,当人们想要确保应用程序在任何 WSGI 条件下(包括多处理条件)运行时,它会变得非常繁重。

例如,一个包含当前连接用户数量的简单变量 - 它应该是进程安全的从 memcached 读/写到 memcached 还是一个 DB 或(如果这种超出标准的库机制是可用)共享内存?

代码会喜欢

counter = 0

@app.route('/login')
def login():
    ...
    counter += 1
    ...

@app.route('/logout')
def logout():
    ...
    counter -= 1
    ...

@app.route('/show_users_count')
def show_users_count():
    return counter

在多处理环境中表现不可预测?

谢谢!

最佳答案

您的问题需要考虑几个方面。

首先,apache MPM 和 mod_wsgi 应用程序之间的交互。如果您在嵌入式模式下运行 mod_wsgi 应用程序(不需要 WSGIDaemonProcessWSGIProcessGroup %{GLOBAL}),您将从 apache MPM 继承多处理/多线程。这应该是最快的选项,并且您最终会拥有多个进程和每个进程的多个线程,具体取决于您的 MPM 配置。相反,如果您在守护程序模式下运行 mod_wsgi,WSGIDaemonProcess <name> [options]WSGIProcessGroup <name> ,您可以以较小的 overhead 为代价对多处理/多线程进行精细控制.

在单个 apache2 服务器中,您可以定义零个、一个或多个命名 WSGIDaemonProcess es,并且每个应用程序都可以在这些进程之一中运行( WSGIProcessGroup <name> )或在嵌入式模式下运行 WSGIProcessGroup %{GLOBAL} .

您可以通过检查 wsgi.multithread 来检查多处理/多线程。和 wsgi.multiprocess变量。

根据您的配置WSGIDaemonProcess example processes=5 threads=1您有 5 个独立的进程,每个进程都有一个执行线程:没有全局数据,没有共享内存,因为您无法控制生成子进程,但 mod_wsgi 正在为您完成。为了共享全局状态,您已经列出了一些可能的选项:进程接口(interface)的数据库、某种基于文件系统的持久性、守护进程(在 apache 之外启动)和基于套接字的 IPC。

正如 Roland Smith 所指出的,后者可以通过 multiprocessing.managers 使用高级 API 来实现。 : 在 apache 之外创建并启动 BaseManager服务器进程

m = multiprocessing.managers.BaseManager(address=('', 12345), authkey='secret')
m.get_server().serve_forever()

在你的应用程序中,你 connect :

m = multiprocessing.managers.BaseManager(address=('', 12345), authkey='secret')
m.connect()

上面的例子是假的,因为 m没有注册有用的方法,但是 here (python 文档)您将了解如何在您的进程中创建和代理一个对象(如示例中的 counter)。

对您的示例的最后评论,带有 processes=5 threads=1 .我知道这只是一个示例,但在实际应用中,我怀疑性能与 processes=1 threads=5 相当。 :只有在“单进程多线程”模型的预期性能提升显着的情况下,您才应该了解在多处理中共享数据的复杂性。

关于Python、WSGI、多处理和共享数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12715139/

有关Python、WSGI、多处理和共享数据的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  4. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  7. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  8. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  9. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐