V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
TcDhl
V2EX  ›  Python

请教一下 Gunicorn 的一些疑惑

  •  
  •   TcDhl · 2022-06-02 16:48:27 +08:00 · 2860 次点击
    这是一个创建于 905 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如果 Flask + Gunicorn 长时间运行, gunicorn 的进程不释放,服务器内存就会一直增长, 会造成内存泄漏

    然后 gunicorn 有两个参数"--max-requests INT"和"--max-requests-jitter INT", 这两个参数可以定期自动清理"gunicorn 的每个 worker"的进程, 避免服务器 GG

    但我有一些疑惑:
    1.如果在自动清理的过程中, 有新的请求动作 进行数据库的增删改查, 这个新的请求动作会不会被清理掉
    2.如果在自动清理的过程中, 已有的进程内正在进行数据库的增删改查, 这个已有的进程不知道会不会被清理
    如果 1. 2. 不会被清理掉, 那这套部署方式应该还比较完美
    有木有大佬知道我疑惑的这两点应该要担心么

    最终线上部署应该是可以弄成 Nginx + Gunicorn + Gevent + Flask 实现高并发
    第 1 条附言  ·  2022-06-02 20:46:03 +08:00
    #1 和#3 的老哥完美解答 !
    有需要可以去参考
    8 条回复    2022-06-06 10:34:02 +08:00
    fgwmlhdkkkw
        2
    fgwmlhdkkkw  
       2022-06-02 17:53:27 +08:00
    这编译器铁定有问题,Microsoft 不过如此……()
    victorc
        3
    victorc  
       2022-06-02 18:02:22 +08:00   ❤️ 1
    这种细节问题,直接去翻代码啊,这是提升技术水平的好办法

    就你问题本身,workder 的 max request 到达上限之后,会把当前请求处理完,不接受新连接进来

    "Autorestarting worker after current request."
    TcDhl
        4
    TcDhl  
    OP
       2022-06-02 20:21:21 +08:00
    TcDhl
        5
    TcDhl  
    OP
       2022-06-02 20:21:38 +08:00
    @julyclyde #1
    @victorc #3
    谢谢两位哥
    Kobayashi
        6
    Kobayashi  
       2022-06-02 21:36:32 +08:00 via Android   ❤️ 3
    Gunicorn 采用 arbiter/manager + worker 管理进程。

    arbiter 作为管理者,不断循环,在每轮循环检测 worker 状态,比如杀死超时 worker ,创建新 worker 。
    而 worker 负责处理请求,多个 worker 监听在同一个 socket 上接受新请求。worker 模式多样,最简单的就是进程模式和线程模式。

    max request 被设计用来限制一个 worker 所能处理的做法请求数量。其初衷是担心代码中内存泄漏,worker 运行一段时间后能被杀死,回收掉内存。

    worker 里边也是循环处理新请求。在每次处理请求前,worker touch 一个 WorkerTmp 对象(好像是一个文件来着),更新其时间戳。而 arbiter 每轮循环检测到 worker.tmp ,就明白 worker 空闲有一定时间了,会干掉它。Arbiter.run() 是循环代码,Arbiter.murder_worker() 尝试清理 worker 。

    Arbiter 管理 worker 方式基于信号。Arbiter 和 Worker 实例化时都会初始化自己的信号管理函数。总之 arbiter 发送 abrt 或者 kill 信号给 worker ,空转 worker 接受到信号后自杀。( worker 空转是因为其达到最大请求数后不再处理新请求)根据 base worker 中 abrt 信号处理函数,worker 执行了 sys.exit(1) 直接退出。

    max requests jitter 是在最大请求数目上加点抖动值,避免所有 worker 同一时间停止接受新请求,服务摊了。不过我觉得请求耗时不大可能完全一样,加不加差不大多。

    Gunicorn vs Uvicorn vs Supervisor

    Gunicorn 很独特的一点是,它既是一个 wsgi 服务器(对标 Uvicorn ),也是一个进程管理器(对标 supervisor )。所以你看到过 Gunicorn+ Uvicorn 部署 asgi 应用,Uvicorn 作为一个 gunicorn 运行。和 supervisor 相比,Gunicorn 进程管理方式相对较弱,完全基于信号,好像 supervisor 基于 RPC 调用啥的,交互式 shell 管理进程、web page 管理进程一应俱全。

    主要相关代码参考 arbiter.py 和 workers/base.py
    TcDhl
        7
    TcDhl  
    OP
       2022-06-02 22:52:10 +08:00
    @Kobayashi #6

    谢谢老哥
    julyclyde
        8
    julyclyde  
       2022-06-06 10:34:02 +08:00
    但是我在 sync worker base 里边没有看到这个功能。没明白咋回事
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2730 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:06 · PVG 23:06 · LAX 07:06 · JFK 10:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.