作者:麥克煎蛋 出處:https://www.cnblogs.com/mazhiyong/ 轉載請保留這段聲明,謝謝!
我們這里不使用容器進行部署。使用容器部署可參考:https://fastapi.tiangolo.com/deployment/
一、安裝ASGI兼容Server
我們選擇Uvicorn作為ASGI Server。
Uvicorn,是一個閃電般快速的ASGI服務器,基於uvloop和httptools構建。
pip install uvicorn
Uvicorn可按以下方式運行我們的應用:
uvicorn main:app --host 0.0.0.0 --port 80
INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
二、使用進程管理器
pip install guvicorn
使用進程管理器確保以彈性方式運行運行多個進程。一個進程管理器將會處理套接字設置,啟動多個服務器進程,監控進程活動,監聽進程重啟、關閉等信號。
Uvicorn 提供一個輕量級的方法來運行多個工作進程,比如 `--workers 4`,但並沒有提供進程的監控。
Gunicorn 是成熟的,功能齊全的服務器,Uvicorn 內部包含有 Guicorn 的 workers 類,允許你運行 ASGI 應用程序,這些 workers 繼承了所有 Uvicorn 高性能的特點。
使用 Guicorn 來進行進程管理,我們可以動態增加或減少進程數量,平滑地重啟工作進程,或者升級服務器而無需停機。
在生產環境中,Guicorn 大概是最簡單的方式來管理 Uvicorn 了,生產環境部署我們推薦使用 Guicorn 和 Uvicorn 的 worker 類:
gunicorn example:app -w 4 -k uvicorn.workers.UvicornWorker
執行上述命令將創建 4 個工作進程,其中 UvicornWorker的實現使用 uvloop 和httptools 實現。
Gunicorn 為 Uvicorn 提供了不同的配置選項集,但是一些配置暫不支持,如--limit-concurrency
。
三、部署實踐
工程目錄結構如下:
├── app │ ├── __init__.py (程序入口) │ └── routers │ ├── __init__.py │ ├── items.py │ └── users.py ├── run.py (服務器運行入口) ├── local.py (本地運行入口) ├── gunicorn.py (Gunicorn設置信息)
1、修改程序入口文件
將初始化代碼放到app目錄下的__init__.py文件中:
import os from fastapi import Depends, FastAPI, Header, HTTPException from .routers import items, users def create_app(): """Create and configure an instance of the Flask application.""" app = FastAPI() async def get_token_header(x_token: str = Header(...)): if x_token != "fake-super-secret-token": raise HTTPException(status_code=400, detail="X-Token header invalid") app.include_router(users.router) app.include_router( items.router, prefix="/items", tags=["items"], dependencies=[Depends(get_token_header)], responses={404: {"description": "Not found"}}, ) return app
2、添加啟動文件
local.py
from app import create_app app = create_app()
在開發環境下,通過以下命令啟動應用:
uvicorn local:app --reload
run.py
from app import create_app import logging from fastapi.logger import logger as fastapi_logger from logging.handlers import RotatingFileHandler app = create_app() # 將日志保存到文件中 formatter = logging.Formatter( "[%(asctime)s.%(msecs)03d] %(levelname)s [%(thread)d] - %(message)s", "%Y-%m-%d %H:%M:%S") handler = RotatingFileHandler('/data/log/abc.log', backupCount=0) logging.getLogger().setLevel(logging.NOTSET) fastapi_logger.addHandler(handler) handler.setFormatter(formatter) fastapi_logger.info('****************** Starting Server *****************')
Gunicorn配置文件(gunicorn.py)
# Gunicorn的配置可以參考:
# https://blog.csdn.net/y472360651/article/details/78538188
# https://docs.gunicorn.org/en/stable/settings.html#server-mechanics
debug = True daemon = True bind = '0.0.0.0:9000' # 綁定ip和端口號 # backlog = 512 # 監聽隊列 chdir = '/data/fastest' # gunicorn要切換到的目的工作目錄 timeout = 30 # 超時 # worker_class = 'gevent' #使用gevent模式,還可以使用sync 模式,默認的是sync模式 work_class = 'uvicorn.workers.UvicornWorker' # workers = multiprocessing.cpu_count() * 2 + 1 # 進程數 # threads = 2 #指定每個進程開啟的線程數 loglevel = 'debug' # 日志級別,這個日志級別指的是錯誤日志的級別,而訪問日志的級別無法設置 access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' # 設置gunicorn訪問日志格式,錯誤日志無法設置 """ 其每個選項的含義如下: h remote address l '-' u currently '-', may be user name in future releases t date of the request r status line (e.g. ``GET / HTTP/1.1``) s status b response length or '-' f referer a user agent T request time in seconds D request time in microseconds L request time in decimal seconds p process ID """
# 如果使用service啟動,這里的pid路徑應與service的pid路徑保持一致,否則無法啟動 pidfile = "/data/log/fast.pid"
accesslog = "/data/log/gunicorn_fasttest_access.log" # 訪問日志文件 errorlog = "/data/log/gunicorn_fasttest_error.log" # 錯誤日志文件
3、生產環境啟動應用
通過腳本可以自動拉取或更新代碼到部署目錄,然后切換到部署目錄下,即可通過以下命令管理應用:
systemctl start/stop/restart gunicorn_fast.service
gunicorn_fast.service內容如下:
[Unit] Description=Gunicorn fast After=syslog.target network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/data/log/fast.pid
# 這里使用了虛擬環境下的Gunicorn ExecStart=/root/.virtualenvs/ppcms/bin/gunicorn -c /data/fastest/gunicorn.py run:app ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
4、nginx層
用戶訪問首先到達nginx層,然后再向后端轉發,詳細部署暫略。