最近做自己个人的一个项目,利用python和flask开发,在Ubuntu16.04上面部署,所以记录了部署的过程,整个过程利用的工具有:Flask,Nginx,Gunicorn,Supervisor,下面我会按顺序来一一介绍

Flask

Flask是python语言中一个有名的开源web框架,在python语言中,有两大主流的web开发框架,一个是Django,另外就是Flask,从github上的火热程度来看,这两个都比较火,二者的区别就是Django比较规范笨拙,集成度高,功能齐全,Flask比较灵活,很多功能都是靠插件来实现。每个人有每个人的喜好,根据自己喜好和项目需要来选择。
flask的官方文档

安装

python 开发,最好借助pip来安装各种需要的包,没有的话,可以直接安装

1
sudo apt-get install pip

如果你要在纯洁的虚拟环境里面开发项目可以安装virtualenv,借助它来生产环境,剩下的具体看官网文档

1
sudo pip install virtualenv

另外一种是全局安装,直接运行

1
sudo pip install Flask

安装好之后,可以运行flas -version,结果显示如下,即表示安装成功

1
2
3
Flask 0.12.2
Python 2.7.12 (default, Dec 4 2017, 14:50:18)
[GCC 5.4.0 20160609]

之后可以写一个脚本来测试运行一下,在/home/{yourusername}/目录下新建一个目录表示项目位置,

1
2
mkdir myapp
vim hello.py

把下面内容添加进hello.py,构成了一个简单的web接口程序,运行在本机8080端口

1
2
3
4
5
6
7
8
9
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(port=8080)

然后运行python hello.py,再访问http://127.0.0.1:8080就可以看到效果
这是flask自带的内置启动服务器功能,方便我们本地开发调试,下面第二步我们采用Gunicorn来启动web服务

Gunicorn安装和配置

Gunicorn“绿色独角兽”是一个被广泛使用的高性能的Python WSGI UNIX HTTP服务器,移植自Ruby的独角兽(Unicorn )项目,使用pre-fork worker模式,具有使用非常简单,轻量级的资源消耗,以及高性能等特点。
Gunicorn 服务器作为wsgi app的容器,能够与各种Web框架兼容(flask,django等),得益于gevent等技术,使用Gunicorn能够在基本不改变wsgi app代码的前提下,大幅度提高wsgi app的性能。

安装gunicorn

直接执行

1
pip install gunicorn

配置gunicorn

在第一步创建的hello.py同级目录创建一个gunicorn配置文件deploy_config.py

1
2
3
4
5
6
7
8
import os
bind='127.0.0.1:8080' #绑定的端口
workers=4 #worker数量
backlog=2048
debug=True
proc_name='gunicorn.pid'
pidfile='/var/log/gunicorn/debug.log' # 此处需要去对于的目录创建debug.log文件,最好以root身份创建,不然在启动的时候会报文件写权限问题,还得改权限
loglevel='debug'

启动gunicorn:

1
gunicorn -c deploy_config.py myapp:app

myapp 是入口Python文件名,app 是Flask 实例名。如果输出 worker 相关信息,表明启动成功。

Nginx安装和配置

Nginx的介绍和牛叉之处这里就不介绍了,全球各大厂商基本都用!

安装nginx

直接执行

1
sudo apt-get install nginx

配置nginx

修改 /etc/nginx/sites-available/ 下的defalut 文件为如下内容:

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name example.com; # 这是HOST机器的外部域名,用IP地址也行
location / {
proxy_pass http://127.0.0.1:8080; # 这里是指向 gunicorn host 的服务地址
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

配置完了之后软链接一份到 /etc/nginx/sites-enabled/defalut 下面

1
ln -s /etc/nginx/sites-available/defalut /etc/nginx/sites-enabled/defalut

注:也可以删除default 文件的,新建自己的配置文件,并建立软链接。

Supervisor安装和配置

Supervisor 是一个用 Python 写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是 Python 进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用 supervisor 同时启动所有应用程序而不是一个一个地敲命令启动。

安装Superisor

直接执行

1
sudo pip install supervisor

首先来看 supervisord 的配置文件。安装完 supervisor 之后,可以运行echo_supervisord_conf 命令输出默认的配置项,也可以重定向到一个配置文件里:

1
echo_supervisord_conf > /etc/supervisord.conf

配置文件中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[program:myapp]
command=/home/www/myapp/py3env/bin/gunicorn -c /home/www/myapp/deploy_config.py myapp:app
autorstart=true
directory=/home/www/myapp
autorestart=true
startsecs=10
startretries=20
[program:nginx]
command=/usr/sbin/nginx
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
stdout_logfile=/var/deploy/log/nginx.log
stderr_logfile=/var/deploy/log/nginx.err

如出现端口占用的错误,则:

1
2
sudo unlink /tmp/supervisor.sock
sudo unlink /var/run/supervisor.sock

启动 Supervisord:

1
supervisord -c /etc/supervisord.conf

关闭 supervisor:

1
supervisorctl shutdown

重新载入配置:

1
supervisorctl reload

最效果就是

访问自己的云服务器ip:port可以看到效果

补充知识点:

Linux 命令

监听端口:

1
2
3
4
5
lsof -i tcp | grep LISTEN
******************************
sshd 837 root 3u IPv4 8888 0t0 TCP *:ssh (LISTEN)
vsftpd 4463 root 3u IPv4 19989 0t0 TCP *:ftp (LISTEN)

nginx知识点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
tree /etc/nginx/
/etc/nginx/
├── conf.d
├── fastcgi_params
├── koi-utf
├── koi-win
├── mime.types
├── naxsi_core.rules
├── naxsi.rules
├── naxsi-ui.conf.1.4.1
├── nginx.conf
├── proxy_params
├── scgi_params
├── sites-available
│   └── default
├── sites-enabled
│   └── default -> /etc/nginx/sites-available/default
├── uwsgi_params
└── win-utf
  • 文件夹 sites-enabled 中的文件为 sites-available 文件夹中文件的硬链接。
    配置文件从 sites-avalidable中加载,默认配置文件为其中的default` 文件。
  • nginx.conf 为主配置文件。
  • uwsgi_parems 是与 Python 相关的文件。
  • fastcgi_parms 是与 PHP 相关的文件。
  • nginx 的默认网站目录 /usr/share/nginx/html。

常用命令:

1
2
3
4
nginx -s stop 快速关闭 nginx
nginx -s quit 优雅的关闭 nginx
nginx -s reload 重新加载配置
nginx -s reopen 重新打开日志文件

获取所有运行中的 nginx 进程列表:

1
ps -ax | grep nginx

若 nginx 主进程 pid 为 1628,则可用kill命令发送 QUIT 信号,关闭此进程:

1
kill -s QUIT 进程ID

supervisor补充

Supervisor 相当强大,提供了很丰富的功能,不过我们可能只需要用到其中一小部分。安装完成之后,可以编写配置文件,来满足自己的需求。为了方便,我们把配置分成两部分:supervisord(supervisor 是一个 C/S 模型的程序,这是 server 端,对应的有 client 端:supervisorctl)和应用程序(即我们要管理的程序)。

配置文件中出去很多注释,主要有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[unix_http_server]
file=/tmp/supervisor.sock ; UNIX socket 文件,supervisorctl 会使用
;chmod=0700 ; socket 文件的 mode,默认是 0700
;chown=nobody:nogroup ; socket 文件的 owner,格式: uid:gid
;[inet_http_server] ; HTTP 服务器,提供 web 管理界面
;port=127.0.0.1:9001 ; Web 管理后台运行的 IP 和端口,如果开放到公网,需要注意安全性
;username=user ; 登录管理后台的用户名
;password=123 ; 登录管理后台的密码
[supervisord]
logfile=/tmp/supervisord.log ; 日志文件,默认是 $CWD/supervisord.log
logfile_maxbytes=50MB ; 日志文件大小,超出会 rotate,默认 50MB
logfile_backups=10 ; 日志文件保留备份数量默认 10
loglevel=info ; 日志级别,默认 info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ; pid 文件
nodaemon=false ; 是否在前台启动,默认是 false,即以 daemon 的方式启动
minfds=1024 ; 可以打开的文件描述符的最小值,默认 1024
minprocs=200 ; 可以打开的进程数的最小值,默认 200
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; 通过 UNIX socket 连接 supervisord,路径与 unix_http_server 部分的 file 一致
;serverurl=http://127.0.0.1:9001 ; 通过 HTTP 的方式连接 supervisord
; 包含其他的配置文件
[include]
files = relative/directory/*.ini ; 可以是 *.conf 或 *.ini

我们把上面这部分配置保存到 /etc/supervisord.conf(或其他任意有权限访问的文件),然后启动 supervisord(通过 -c 选项指定配置文件路径,如果不指定会按照这个顺序查找配置文件:$CWD/supervisord.conf, $CWD/etc/supervisord.conf, /etc/supervisord.conf)

program 配置
上面我们已经把 supervisrod 运行起来了,现在可以添加我们要管理的进程的配置文件。可以把所有配置项都写到 supervisord.conf 文件里,但并不推荐这样做,而是通过 include 的方式把不同的程序(组)写到不同的配置文件里。

为了举例,我们新建一个目录 /etc/supervisor/ 用于存放这些配置文件,相应的,把 /etc/supervisord.conf 里 include 部分的的配置修改一下:

1
2
[include]
files = /etc/supervisor/*.conf

假设有个用 Python 和 Flask 框架编写的用户中心系统,取名 usercenter,用 gunicorn (http://gunicorn.org/) 做 web 服务器。项目代码位于 /home/leon/projects/usercenter,gunicorn 配置文件为 gunicorn.py,WSGI callable 是 wsgi.py 里的 app 属性。所以直接在命令行启动的方式可能是这样的:

1
2
cd /home/leon/projects/usercenter
gunicorn -c gunicorn.py wsgi:app

现在编写一份配置文件来管理这个进程(需要注意:用 supervisord 管理时,gunicorn 的 daemon 选项需要设置为 False):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[program:usercenter]
directory = /home/leon/projects/usercenter ; 程序的启动目录
command = gunicorn -c gunicorn.py wsgi:app ; 启动命令,可以看出与手动在命令行启动的命令是一样的
autostart = true ; 在 supervisord 启动的时候也自动启动
startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true ; 程序异常退出后自动重启
startretries = 3 ; 启动失败自动重试次数,默认是 3
user = leon ; 用哪个用户启动
redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20 ; stdout 日志文件备份数
; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile = /data/logs/usercenter_stdout.log
; 可以通过 environment 来添加需要的环境变量,一种常见的用法是修改 PYTHONPATH
; environment=PYTHONPATH=$PYTHONPATH:/path/to/somewhere

一份配置文件至少需要一个 [program:x] 部分的配置,来告诉 supervisord 需要管理那个进程。[program:x] 语法中的 x 表示 program name,会在客户端(supervisorctl 或 web 界面)显示,在 supervisorctl 中通过这个值来对程序进行 start、restart、stop 等操作。

  • 使用 supervisorctl
    Supervisorctl 是 supervisord 的一个命令行客户端工具,启动时需要指定与 supervisord 使用同一份配置文件,否则与 supervisord 一样按照顺序查找配置文件。
    1
    supervisorctl -c /etc/supervisord.conf

上面这个命令会进入 supervisorctl 的 shell 界面,然后可以执行不同的命令了

1
2
3
4
5
6
> status # 查看程序状态
> stop usercenter # 关闭 usercenter 程序
> start usercenter # 启动 usercenter 程序
> restart usercenter # 重启 usercenter 程序
> reread # 读取有更新(增加)的配置文件,不会启动新添加的程序
> update # 重启配置文件修改过的程序

上面这些命令都有相应的输出,除了进入 supervisorctl 的 shell 界面,也可以直接在 bash 终端运行:

1
2
3
4
5
6
$ supervisorctl status
$ supervisorctl stop usercenter
$ supervisorctl start usercenter
$ supervisorctl restart usercenter
$ supervisorctl reread
$ supervisorctl update

  • 其他
    除了 supervisorctl 之外,还可以配置 supervisrod 启动 web 管理界面,这个 web 后台使用 Basic Auth 的方式进行身份认证。

除了单个进程的控制,还可以配置 group,进行分组管理。

经常查看日志文件,包括 supervisord 的日志和各个 pragram 的日志文件,程序 crash 或抛出异常的信息一半会输出到 stderr,可以查看相应的日志文件来查找问题。

Supervisor 有很丰富的功能,还有其他很多项配置,可以在官方文档获取更多信息:http://supervisord.org/index.html