Gunicorn源码阅读与分析(一)——Gunicorn的整体运行轨迹

阿凡达2018-07-20 10:19

Gunicorn的运行流程

源代码阅读时,最好能够了解项目的运行流程,从整体上感知运行的过程,方便对项目进行分解,逐步学习。通过文章[运行Gunicorn源码][1]的介绍,并结合pdb进行逐步调试, 很容易的获得Gunicorn的整体运行过程,如下图:

Gunicorn整体运行过程说明

  1. app/wsgiapp.py中的run()函数是项目的启动入口,该函数会调用app/wsgiapp.pyWSGIApplication类的run()方法, 毕竟Gunicorn是个WSGI应用服务器;
  2. WSGIApplication类的run()方法继承自app/base.pyBaseApplication类, 该BaseApplication类还有其它的子类,如:DjangoApplicationPasterBaseApplication等。 所以将run()定义在BaseApplication这个父类中。BaseApplication.run()方法会调用arbiter.pyArbiter类的run()方法。
  3. 前面已经提到过, Gunicorn基于prefork模式,通过主进程来fork出工作者进程,然后由工作者进程取处理请求。而这里的arbiter("仲裁者"的意思), 就是指主进程Arbiter.run()的主要代码结构如A框中所示。首先, arbiter(主进程)会先根据配置调用spawn_workers()方法去创建指定数量(默认是1)的工作者进程数量,然后进入一个while True的循环, 在这个循环里面, 主进程接收信号,并根据信号来管理工作者进程, 所以:主进程是不直接处理用户的HTTP请求的。
  4. spawn_workers()方法会通过循环来调用spawn_worker()方法, 从而创建多个工作者进程。
  5. spawn_worker()方法中, 会通过查看配置,来生成指定类型的工作者进程,如:

    worker = self.worker_class(self.worker_age, self.pid, self.LISTENERS, self.app, self.timeout / 2.0, self.cfg, self.log)

    这里的worker_class是可以通过参数指定的.

    worker创建好以后, 会调用workers/base.pyWorker类的init_process()方法

  6. Worker.init_process()中, 会完成对工作者进程的准备工作, 如:加载配置、初始化信号量等。然后调用Workder.run()方法来启动工作者进程。

  7. 由于Gunicorn支持多种工作者进程, 每种工作者进程的运行过程不同, 所以Workder.run()会由子类去实现, 这里用到了模板设计模式

本文来自网易实践者社区,经作者王一兵授权发布。