方案背景
系统版本:debian9
环境搭配:python3
虚拟环境 + fastapi
+ uvicorn
+ gunicorn
项目根目录: /data/wwwroot/domian.com
官方文档中是以 IP:PORT
形式启动 fastapi
,但每次都要进虚拟环境通过命令启动 gunicorn
,贼麻烦。后来改成 systemd
+ gunicorn
的方式后,开机自动启动 gunicorn
而且不占用端口。
具体部署 fastapi
另外写文章说明,本文章只说 nginx
+ systemd
+ gunicorn
的配置方式。
大概方案
新建以下文件:
/etc/systemd/system/gunicorn.service
/etc/systemd/system/gunicorn.socket
nginx
的 conf
文件中 不用代理 ip:prot
形式,而是代理sock
文件。
具体步骤
在项目根目录创建 gunicorn
的配置文件 gconfig.py
,其内容:
# coding=utf-8
# from gevent import monkey
# monkey.patch_all()
# import multiprocessing
debug = True
# 修改代码时自动重启
reload = True
#
reload_engine = 'inotify'
# //绑定与Nginx通信的端口
# bind = '127.0.0.1:3002'
bind = 'unix:/data/wwwroot/domian.com/tmp/gunicorn.sock'
pidfile = 'log/gunicorn.pid'
workers = 4 # 进程数
# workers = multiprocessing.cpu_count() * 2 + 1 #进程数
worker_class = 'uvicorn.workers.UvicornWorker' # 使用 unicorn ,不使用 gunicorn 自带的方式. unicorn相关文档: http://www.uvicorn.org/deployment/#running-gunicorn-worker
# 日志级别
# debug:调试级别,记录的信息最多;
# info:普通级别;
# warning:警告消息;
# error:错误消息;
# critical:严重错误消息;
loglevel = 'debug'
# 访问日志路径
accesslog = 'log/gunicorn_access.log'
# 错误日志路径
errorlog = 'log/gunicorn_error.log'
# 设置gunicorn访问日志格式,错误日志无法设置.貌似无效
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
# 执行命令
# gunicorn -c gconfig.py main:app
# gunicorn -c gconfig.py main:app -k uvicorn.workers.UvicornWorker
'''
自动执行
使用 supervisor
https://docs.gunicorn.org/en/stable/deploy.html#supervisor
参考资料:
https://www.jianshu.com/p/bbd0b4cfcac9
https://www.cnblogs.com/tk091/archive/2014/07/22/3859514.html
'''
/etc/systemd/system/gunicorn.service
:
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
Type=notify
# the specific user that our service will run as
User=gunicorn
Group=www
# another option for an even more restricted service is
# DynamicUser=yes
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
RuntimeDirectory=gunicorn
# WorkingDirectory 是项目路径目录
WorkingDirectory=/data/wwwroot/domian.com
# 代替手动执行的命令,
# 原本在虚拟环境中要执行的 gunicorn -c gconfig.py main:app -k uvicorn.workers.UvicornWorker
# 其中 gunicorn 和 gconfig.py 要写完整的路径名称
ExecStart=/data/wwwroot/domain.com/venv/bin/gunicorn -c /data/wwwroot/domain.com/gconfig.py main:app -k uvicorn.workers.UvicornWorker
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
/etc/systemd/system/gunicorn.socket
:
[Unit]
Description=gunicorn socket
[Socket]
# ListenStream 写要生成的 sock 文件路径,要写完整路径。我是放到项目根目录下的。
ListenStream=/data/wwwroot/domian.com/tmp/gunicorn.sock
# Our service won't need permissions for the socket, since it
# inherits the file descriptor by socket activation
# only the nginx daemon will need access to the socket
User=www-data
# Optionally restrict the socket permissions even more.
# Mode=600
[Install]
WantedBy=sockets.target
nginx
的 domian.conf
,其它配置不写,主要是 /
代理这部分:
location / {
# 放弃原始 ip 端口形式,改为代理到 sock 文件
# proxy_pass http://127.0.0.1:3002;
# unix 后面的路径就是前面文件中的 sock 文件的完整路径,注意格式。
proxy_pass http://unix:/data/wwwroot/domian.com/tmp/gunicorn.sock;
}
操作命令
重启 nginx
后,会自动生成 domian_gunicorn.sock
,然后打开域名确认 fastapi
应用是否正常启动:
systemctl reload nginx.service
systemctl restart nginx.service
开机启动并立即启动 gonicorn.socket
:
systemctl enable gunicorn.socket --now
不同的操作命令:
启动: systemctl start gunicorn.service
状态:systemctl status gunicorn.service
停止:systemctl stop gunicorn.service
重启:systemctl restart gunicorn.service
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。