zoukankan      html  css  js  c++  java
  • 【原创】uwsgi中多进程+多线程原因以及串行化accept()

    如有不对,请详细指正。

      最近再研究uwsgi如何部署python app,看uwsgi的文档,里面有太多的参数,但每个参数的解释太苍白,作为菜鸟的我实在是不懂。想搞清楚uwsgi的工作原因以及里面的一些参数的意义,只能通过英文的文档和源码来入手,虽然慢,但是理解更深刻。

      本文根据代码阅读以及参照多种文档,描述了uwsgi的启动多进程+多线程工作原因,以及thunder_lock参数的作用:

    • uwsgi是用c语言写的一个webserver,可以启动多个进程,进程里面可以启动多个线程来服务。进程分为主进程和worker进程,worker里面可以有多个线程。
    • 一开始进入main函数,启动这个就是主进程了,uwsgi_setup函数(主进程)里面针对选项参数做一些处理,执行环境设置,执行一些hook,语言环境初始化(python),如果没有设置延迟加载app,则app在主进程加载;如果设置了延迟加载,则在每一个worker进程中都会加载一次。uwsgi_setup函数还执行了插件的初始化(当前我只关心http、python:http是gateway类型的插件,这种插件是向外暴露http服务的,python的requests类型的插件,用来服务请求的)、tcp socket的绑定与监听(这个是指http与work之间的通信,且它的端口是自动产生的)。最后uwsgi主进程fork了指定worker进程用来接收(accept)请求。虽然在setup中就fork了子进程,但是现在还没有开始accept。
    • wsgi_run函数就是真正的开始执行了,这个函数分为俩个部分,主进程执行部分和worker进程执行部分。主进程执行部分是一个无限循环,他可以执行特定的hook以及接收信号等,总之是用来管理worker进程以及一些定时或者事件触发任务。worker部分:注册型号处理函数,执行一些hook,循环接收(accept)请求。在启动woker时可以根据--threads参数指定要产生的线程个数,否则只在当前进程启动一个线程。这些线程循环接收请求并处理。
    • 在worker中接收请求的函数wsgi_req_accept有一个锁:thunder_lock,这个锁用来串行化accept,防止“惊群”现象:参考这里
      •   惊群现象出现在这样的情况:主进程绑定并监听socket,然后调用fork,在各个子进程进行accept。无论任何时候,只要有一个连接尝试连接,所有的子进程都将被唤醒,但只有一个会连接成功,其他的会得到一个EAGAIN的错误,浙江导致巨大的CPU资源浪费,如果在进程中使用线程,这个问题被再度放大。一个解决方法是串行化accept,在accept前防止一个锁。
  • 相关阅读:
    UVA 10480 Sabotage (最大流最小割)
    bzoj2002 [Hnoi2010]Bounce 弹飞绵羊 (分块)
    poj3580 SuperMemo (Splay+区间内向一个方向移动)
    bzoj1500: [NOI2005]维修数列 (Splay+变态题)
    hdu3436 Queue-jumpers(Splay)
    hdu4710 Balls Rearrangement(数学公式+取模)
    hdu1890 Robotic Sort (splay+区间翻转单点更新)
    zoj2112 Dynamic Rankings (主席树 || 树套树)
    poj3581 Sequence (后缀数组)
    notepa++ Emmet的安装方法
  • 原文地址:https://www.cnblogs.com/pengyusong/p/5767899.html
Copyright © 2011-2022 走看看