简介

FastAPI是一个可快速构建API服务的Web框架,可与 NodeJS 和 Go 比肩的极高性能(归功于 Starlette 和 Pydantic),是最快的 Python Web 框架之一。更多详情见官网FastAPI官网地址

本文对FastAPI的开发部署以及生产环境部署做一个记录。

开发部署

安装uvicorn作为asgi应用服务器

pip install uvicorn

例:main.py

from fastapi import FastApi

app = FastApi()


@app.get('/hello')
async def hello():
    return {'message': 'hello World'}

nvicorn main:app --reload 开发模式下运行 热加载

如果是想在Pycharm等IDE中直接运行,可以在代码中加入

if __name__ == '__main__':
    uvicorn.run("main:app", host="127.0.0.1", port=8000, log_level="info")

即可直接run运行,不需要使用命令行,但只适合用于开发环境。

生产环境部署

生产环境:CentOS7.x +Nginx

1.安装Gunicorn

Gunicorn 是一个unix上被广泛使用的高性能的Python WSGI UNIX HTTP Server,和大多数的Web框架兼容,并具有实现简单,轻量级,高性能等特点。

使用gunicorn启动应用程序的好处是,它可以处理大量的并发连接,,并且其使用的是预派生子进程的方式,这意味着它能够更好地利用多核CPU。

安装命令

pip install uvicorn
pip install gunicorn

Shell中执行gunicorn -v有版本输出表示安装成功

2.以配置文件方式启动应用

创建gunicorn.py文件,里面包含下列内容

import os

# 设置守护进程
daemon=True
# 监听内网端口8000
bind='0.0.0.0:8000'
# 设置进程文件目录
pidfile='./gunicorn.pid'
chdir='./' # 工作目录
# 工作模式
worker_class='uvicorn.workers.UvicornWorker'
# 并行工作进程数 核心数*2+1个
workers=3  #multiprocessing.cpu_count()+1
# 指定每个工作者的线程数
threads=2
# 设置最大并发量
worker_connections = 2000
loglevel='debug' # 错误日志的日志级别
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
# 设置访问日志和错误信息日志路径
log_dir = "./log"
if not os.path.exists(log_dir):
    os.makedirs(log_dir)
accesslog = "./log/gunicorn_access.log"
errorlog = "./log/gunicorn_error.log"

运行项目

1.上面的gunicorn.py文件配置好后,使用如下命令:

gunicorn main:app -c gunicorn.py

在gunicorn_error.log 文件中看到日志输出表示启动成功。

2.当然也可以不用配置文件,直接执行下面命令启动应用

gunicorn main:app -b 0.0.0.0:8000 -w 4 -k uvicorn.workers.UvicornWorker --daemon

这是一个启动命令,主要作用是使用gunicorn作为应用部署服务器,并指定服务器的启动参数:

  • main:app指定了Gunicorn要运行的应用程序入口点;
  • -b 0.0.0.0:8000指定了服务器的IP地址和端口;
  • -w 4指定了Gunicorn使用4个工作进程同时处理请求;
  • -k uvicorn.workers.UvicornWorker指定使用UvicornWorker作为工作进程的类型;
  • --daemon参数表示将服务器以守护进程(daemon)模式启动(后台运行)。

停止项目

如果想要停止Gunicorn项目,可以先通过查看进程树找到进程pid,然后使用kill命令结束进程

1.获取gunicorn进程树

pstree -ap | grep gunicorn

2.终止gunicorn任务

kill -HUP 进程pid

3.如果使用了多进程,那么执行了上述命令后还会有子进程在运行,可以使用如下命令杀死

kill -9 进程pid

当然,这样一个一个关闭太繁琐了,我们可以编写一个 Shell 脚本,来实现一键杀死所有主进程和子进程的功能。

脚本示例:

#!/bin/bash# 查找 gunicorn 主进程 PID
gunicorn_pid=$(ps aux | grep 'gunicorn' | grep -v 'grep' | awk '{print $2}')# 如果找到了主进程 PID
if [ -n "$gunicorn_pid" ]; then
  echo "Found gunicorn process: $gunicorn_pid"
  
  # 给主进程发 SIGINT 信号,请求正常停止进程
  kill -INT $gunicorn_pid
  
  # 睡眠 5 秒等待主进程结束 
  sleep 5
  
  # 查找所有 gunicorn 子进程 PID
  gunicorn_child_pids=$(pstree -p $gunicorn_pid | grep -oP '([0-9]+)(?=\))')
  
  # 如果找到了子进程 PID
  if [ -n "$gunicorn_child_pids" ]; then
    echo "Found gunicorn child processes: $gunicorn_child_pids"
    
    # 杀死所有子进程
    for pid in $gunicorn_child_pids; do
      kill -9 $pid
    done
  fi
  
  echo "Stopped gunicorn process and child processes"
  
else
  echo "No running gunicorn process found"
fi

这个脚本可以完成以下操作:

  1. 查找 gunicorn 主进程 PID
  2. 给主进程发送 SIGINT 信号请求正常关闭
  3. 睡眠 5 秒等待主进程结束
  4. 使用 pstree 命令查找所有 gunicorn 子进程 PID
  5. 使用 kill 命令杀死所有子进程

您只需要将以上代码保存到一个文件中 (例如 stop_gunicorn.sh),并确保该文件有执行权限,然后在命令行界面运行该脚本,即可一次性停止 gunicorn 进程和所有子进程:

bash stop_gunicorn.sh

配置开机自启(可选)

配置 gunicorn.service服务开机自启动

cat >/usr/lib/systemd/system/gunicorn.service << EOF
[Unit]
Description=Gunicorn fast
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/gunicorn.pid
ExecStart=/root/.local/share/virtualenvs/fastapi-Xq8atoqR/bin/gunicorn  -c 
/opt/web/fastapi/gunicorn.py main:app
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
 
[Install]
WantedBy=multi-user.target
 
EOF

依次执行下面命令

systemctl daemon-reload
systemctl enable gunicorn
systemctl start gunicorn

查看服务状态

systemctl status gunicorn

配置Nginx代理访问(可选)

server {
            listen 80;
           # listen 443 ssl;
            server_name api.hmily.vip;
            access_log  /var/log/nginx/access.log;
            location / {
                proxy_pass http://127.0.0.1:8000;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For
                $proxy_add_x_forwarded_for;
        }
    }

运行nginx -s reload,至此就完成了FastAPI的生产部署 !

docs/redoc文档显示空白问题

有时候我们用不同设备或者浏览器会出现docs/redoc文档空白不能显示的问题,这是因为模板文件用的是外国的cdn,所以国内访问会比较慢,出现访问失败的情况,导致显示空白。

解决办法:

修改FastAPI源文件,把模板文件保存到本地,然后修改文件路径让其从本地访问。

1.首先修改源文件,模板文件路径如下:

fastapi/openapi/docs.py

把docs.py文件里的下面这三行

swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js",
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css",
swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",

修改为

swagger_js_url: str="/static/swagger-ui/swagger-ui-bundle.js",
swagger_css_url: str="/static/swagger-ui/swagger-ui.css",
swagger_favicon_url: str="/static/swagger-ui/favicon.png",

2.修改我们的项目代码,添加下面这段代码

from fastapi.staticfiles import StaticFiles
app.mount('/static', StaticFiles(directory='static'),
          name='static')

注意:directory路径需要根据自己的实际情况设置。

3.把我们的static模板文件放置到项目根目录下,静态文件我放网盘了百度云文件,有需要可自行下载。

最后重新运行我们的项目,便大功告成!

2022.11.06

转至:https://zhuanlan.zhihu.com/p/580791329

Logo

更多推荐