Python素来以慢而闻名。正所谓,“都用Python了,还在乎什么性能”。Django、Flask无不以简单易用而著称,但却距离高性能很远。

Python自3.4版本加入了asyncio库以来,异步编程的生态得到了长足发展。Django基金会发布的ASGI协议,更是将异步HTTP服务器和上层的路由设施解耦开来。由此,高性能的C语言编写的服务器便得到了大施拳脚的空间。

本次介绍的就是利用高性能的路由框架FastAPI和Nginx Unit服务器,组合成为一个高性能的服务端框架, 让你的业务逻辑跑得飞快。

FastAPI,是一个高性能的路由框架。主要负责将解析好的HTTP请求交给合适的代码逻辑来处理。

Nginx Unit,是一个由Nginx团队维护使用C语言编写的高性能HTTP服务器,可以做反向代理、静态代理,也可以做应用服务器。作为应用服务器,Nginx Unit支持Go、Java、JS等多门语言。对于Python语言,Nginx Unit支持WSGI、ASGI两种协议。在Python的使用场景下,Nginx Unit主要负责处理TCP网络连接,以及HTTP报文的接收、解析和发送。

话不多说,直接看代码。

代码结构

这里我把所有的代码、配置都放在同一个目录下fastapi-unit-demo

➜ tree

.
├── config
│   └── config.json                            # Nginx Unit的应用配置
├── docker-compose.yml                         # 启动入口
├── dockerfile                                 # 构建自己的镜像
├── logs
│   └── unit.log                               # 空文件,应用启动后,log会输出在这里
├── requirements.txt                           # 应用的依赖
├── src
│   └── demo.py                                # demo的入口
├── state                                      # 空文件夹,交给Nginx Unit使用
└── tsinghua.mirror                            # 构建镜像使用的清华大学mirror

4 directories, 7 files

Python代码

➜ cat src/demo.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello, World!"}

Nginx Unit配置文件

➜ cat config/config.json

{
    "listeners":{
        "*:80":{
            "pass":"applications/fastapi"    # 这一行关联的是下方的具体配置
        }
    },
    "applications": {
        "fastapi": {
            "type": "python 3.10",           # 和镜像自带的Python版本保持一致
            "path": "/www",                  # 代码的路径
            "module": "demo",                # 启动的入口
            "callable": "app"                # ASGI app的变量名
        }
    }
}

构建镜像

➜ cat dockerfile

FROM nginx/unit:1.27.0-python3.10

COPY requirements.txt /config/requirements.txt
COPY tsinghua.mirror /etc/apt/sources.list

RUN apt update && apt install -y python3-pip                                    \
    && pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \  # 配置pypi镜像,按具体情况可以去掉
    && pip3 install -r /config/requirements.txt                                 \
    && apt remove -y python3-pip                                                \
    && apt autoremove --purge -y                                                \
    && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/*.list

docker-compose配置

➜ cat docker-compose.yml

version: "3.3"
services:
  app:
    build:
      context: .
      dockerfile: dockerfile
    volumes:
      - ./config:/docker-entrypoint.d/
      - ./logs/unit.log:/var/log/unit.log
      - ./state:/var/lib/unit
      - ./src:/www
    ports:
      - 8080:80

启动demo看看

在代码根目录下执行命令:

➜ docker-compose up

启动完成后,打开浏览器,访问http://localhost:8080,就可以看到响应了{"message":"Hello, World!"}

性能一瞥

使用wrk简单的测试一下hello-world性能。CPU是AMD Ryzen 5800X,系统是Debian 11,内核版本5.10。

注意,Nginx Unit服务器默认使用1个线程处理请求,所以Python代码理应跑在单进程模式中。

➜  wrk git:(master) ✗ ./wrk -t2 -c20 -d10s --latency http://localhost:8080

Running 10s test @ http://localhost:8080
  2 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.38ms   56.89us   3.43ms   96.40%
    Req/Sec     7.29k   133.32     7.64k    83.00%
  Latency Distribution
     50%    1.38ms
     75%    1.38ms
     90%    1.39ms
     99%    1.51ms
  145182 requests in 10.00s, 21.60MB read
Requests/sec:  14517.95
Transfer/sec:      2.16MB

对香农计划的未来成果简直更期待了呢~