读源码-Gunicorn篇-5-协议
本节说明
本节的标题是——协议,有两层意思,一个是用户请求的协议 HTTP,另一个是 gunicorn 解析请求后,与我们的应用交互的 WSGI 协议,本章节将分两个部分分别讨论。
开始前,我们先回顾一下 HTTP 协议。
HTTP 协议
HTTP 请求
一个完整的 HTTP 请求包含四个部分:
- 请求行:请求方法 +
URL+HTTP版本 - 请求头:包含各种元数据信息
- 空行:分隔头部和消息体
- 请求体:包含要发送的数据(可选)
示例:
1 | GET /hello?a=123 HTTP/1.1 |
HTTP 响应
一个完整的 HTTP 响应结构也包含四个部分:
- 状态行:
HTTP版本 + 状态码 + 状态描述 - 响应头:服务器返回的元数据信息
- 空行:分隔响应头和响应体
- 响应体:实际返回的数据内容(可选)
示例:
1 | HTTP/1.1 200 OK |
在 HTTP 请求和响应中,除了请求体和响应体部分,其它的可以看作是纯文本的内容。
参照上边的例子,我们来看一下一个用户请求是如何解析交给 WSGI 应用的。
读源码-Gunicorn篇-4-worker
本节说明
上一节我们梳理了 gunicorn 是如何处理配置的,这一节我们来看 gunicorn 的工作进程是如何运行的。
分类
gunicorn 默认实现了 sync、eventlet、gevent、tornado、gthread 这几种类型 worker 的实现,含义如下:
| 名称 | 说明 | 异步 | 实现 |
|---|---|---|---|
| sync | 默认类型,每个worker同一时间只处理一个请求 | 否 | workers.sync.SyncWorker |
| eventlet | 基于 eventlet 实现,需要 monkey patch | 是 | workers.geventlet.EventletWorker |
| gevent | 基于 gevent 实现,需要 monkey patch | 是 | workers.ggevent.GeventWorker |
| tornado | 集成 Tornado 框架的事件循环机制,适合与 Tornado 应用结合使用 | 是 | workers.gtornado.TornadoWorker |
| gthread | 每个 worker 是一个进程,内部开启多个线程同时处理请求 | 否 | workers.gthread.ThreadWorker |
我们从最简单的默认的 sync 类型来看 gunicorn 是如何加载一个 worker 的。
读源码-Gunicorn篇-3-配置
本节说明
上一节我们梳理了 gunicorn 服务启动的流程,本章节我们来研究一下它的配置是如何处理的。
来源
从官方文档中我们可以得知,gunicorn 会从 5 个地方读取配置数据,按优先级从低到高分别是:
- 从环境变量中读取
- 从框架特定的配置文件中读取(目前仅支持
Paster应用) - 从当前工作目录中的
gunicorn.conf.py文件中读取,或通过命令行参数指定这个文件 - 从名称为
GUNICORN_CMD_ARGS的环境变量中读取 - 命令行启动时指定的参数配置
这几个位置读取到的配置优先级依次增加,不同位置配置的相同参数,优先级高的会覆盖优先级低的。
需要注意的是如果像 GUNICORN_CMD_ARGS 和命令行中都指定了配置文件的路径,则只会解析使用命令行中指定的文件,而不是都解析后进行覆盖合并。
了解了配置的来源及优先级,我们来看下 gunicorn 是怎么做的。
读源码-Gunicorn篇-2-启动
本节说明
上一节我们已经可以将服务跑起来了,但是服务器是怎么跑起来的?
本章节我们就来跟踪一下 gunicorn 的启动流程,以及它的进程是如何管理的。
入口
我们知道,一个简单的 gunicorn 服务启动命令,可以在命令行直接输入 gunicorn main:app,那么这个 gunicorn 命令是从哪里来的呢?
在 gunicorn/pyproject.toml 文件中,有这样一个配置段,[project.scripts]:
1 | [project.scripts] |
gunicorn = "gunicorn.app.wsgiapp:run",这个配置就是 gunicorn 程序启动的入口,我们在 pip install gunicorn时,会根据这个配置,在 env/bin 目录生成 gunicorn 的启动脚本,里面的内容是这样的:
1 | #!/Users/chundi/explorer/env/bin/python |
可以看到也是通过 gunicorn.app.wsgiapp:run 启动的,这个 run 方法就是程序的入口。
读源码-Gunicorn篇-1-准备
开篇
开始了,一直想写一些关于阅读源码的东西,终于开始了。
这次选了一个比较熟悉的 python 项目 gunicorn,代码量不大,但功能是完整的,容易阅读,也容易整理,作为一个尝试吧。
本节说明
本章节主要做一些准备工作,包括 python 环境配置,源码获取,源码文件介绍和调试环境准备,在本节结束时,我们应该可以搭建好调试环境,并将服务跑起来。
准备工作
1. 配置python环境
我使用的是 3.12 版本的 python,推荐使用 linux/mac 系统,windows 环境也推荐使用 wsl,环境配置会更方便一些。
首先我们创建一个文件夹,作为我们的项目目录,后续所有的操作都在这个目录中进行。
1 | mkdir explorer && cd explorer |
大家一起读源码 - 前言
博客搭了这么久了,一直想写一些东西,但也一直没有动手开始写,总觉得很多东西看得还不够明白,没有完全弄清楚,写不出什么东西来,各种找借口。。最近越来越觉得,如果一直不写,就永远也写不出来。。
所以现在打算一点一点开始,把一直想写的一个东西写出来,就叫『大家一起读源码』,可能会只有一个项目,也可能会写一个系列出来,写到哪儿算哪儿吧。
嗯,就酱。