读源码-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 |
大家一起读源码 - 前言
博客搭了这么久了,一直想写一些东西,但也一直没有动手开始写,总觉得很多东西看得还不够明白,没有完全弄清楚,写不出什么东西来,各种找借口。。最近越来越觉得,如果一直不写,就永远也写不出来。。
所以现在打算一点一点开始,把一直想写的一个东西写出来,就叫『大家一起读源码』,可能会只有一个项目,也可能会写一个系列出来,写到哪儿算哪儿吧。
嗯,就酱。