部署Flask服务器流程

Monday, December 10, 2018

当我们把 Flask 后台开发完成后,我们会尝试将其部署到云服务器,这里我们以阿里云的 centos7.4为例。

安装基本库和工具

  • 首先我们先将系统环境升级一下

    $ yum update $ yum upgrade

安装Python3.7

  • 由于 centos 并没有自带 python3,所以我们需要安装 python3的环境,并且最好以开发环境的 python 版本一致,否则在后续 pipenv install 的时候会出现些许问题,且处理起来相对比较麻烦,会涉及到多个python3版本的问题。
  • 我的 Mac 环境是以 python3.7的版本进行开发的,所以我们在 centos 上也准备使用 python3.7,由于 python3.7 貌似还没有RPM的直接安装版本,所以我们需要自己去编译 python3.7 安装,这里写下简单的安装过程,其它版本的 Python 可能有些许区别。

安装依赖包

因为使用源码方式安装,所以需要安装 GCC 编译器和 make 编译工具,这些软件包含在 Development tools 软件组中。

<code class="">$ sudo yum group install "Development tools"
</code>

因为 Python 3.7 源文件使用 zlib 格式打包,所以需要安装 zlib 软件包;Python 3.7 编译安装时需要使用 zlib 的头文件和链接库,所以需要安装 zlib 的头文件和链接库 zlib-devel 软件包

<code class="">$ sudo yum -y install zlib zlib-devel
</code>

Python 3 有个内置模块 ctypes,它是 Python 3 的外部函数库(Foreign function library),它需要使用系统外部函数库(libffi)的头文件和链接库,所以需要安装外部函数库(libffi)头文件和链接库 libffi-devel 软件包:

<code class="">$ sudo yum -y install libffi-devel
</code>

配置,编译,安装

<code class="">wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
tar xJf Python-3.7.0.tar.xz
cd Python-3.7.0
sudo ./configure
sudo make
sudo make install
</code>

安装 pipenv

首先我们先安装一些 python 的基础包

<code class="">$ sudo yum install python3-dev python3-pip
</code>

使用 pip 安装 pipenv

<code class="">$ sudo -H pip3 install pipenv
</code>

安装 MysQL

由于我们用的是 mysql 数据库,所以需要先安装好 MySQL 数据库,这里我们用的是5.7版本 下载 mysql 源安装包

<code class="">$ curl -LO http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
</code>

安装 mysql 源

<code class="">$ sudo yum localinstall mysql57-community-release-el7-11.noarch.rpm
</code>

检查 yum 源是否安装成功

<code class="">$ sudo yum repolist enabled | grep "mysql.*-community.*"
mysql-connectors-community           MySQL Connectors Community              21
mysql-tools-community                MySQL Tools Community                   38
mysql57-community                    MySQL 5.7 Community Server             130
</code>

安装

<code class="">$ sudo yum install mysql-community-server
</code>

启动

<code class="">$ sudo systemctl enable mysqld
</code>

启动服务

<code class="">$ sudo systemctl start mysqld
</code>

查看服务状态

<code class="">$ sudo systemctl status mysqld
</code>

修改 root 默认密码 MySQL 5.7 启动后,在 /var/log/mysqld.log 文件中给 root 生成了一个默认密码。通过下面的方式找到 root 默认密码,然后登录 mysql 进行修改

<code class="">$ grep 'temporary password' /var/log/mysqld.log
[Note] A temporary password is generated for root@localhost: **********
</code>

登录 MysQL 并修改密码

<code class="">$ mysql -u root -p
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword1!';
</code>

重启 MySQL 服务,使配置生效

<code class="">sudo systemctl restart mysqld
</code>

推送代码到服务器

接下来我们使用私有 git,将代码 clone 到服务器,但是私有 git 无法直接 clone,我们需要部署 ssh key

Linux 生成 SSH key

我们先检查是否存在 ssh key

<code class="">ls -al ~/.ssh
</code>

如果没有,生成新的 ssh key

<code class="">ssh-keygen -t rsa -C "your_email@example.com"
</code>

然后一路回车就行。。。不用更改名字和密码 将生成的 ssh key 添加到 github 中

<code class="">eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
</code>

再仓库中添加公共 key 之后,就可以将代码 clone 下来了。

部署 pipenv 环境

进入项目目录

<code class="">pipenv install 
pipenv shell
</code>

然后对数据库进行初始化等操作,准备工作就大体完成了

环境变量读取

在本地开发中,我们使用了.env 文件和 .flaskenv来存放配置的环境变量,比如数据库地址,相关的 key 等。在本地开发中,使用 flask run 系统就会自动读取到相关数据,但是我们部署在服务器并不会用这个,而是用 gunicorn 等工具。这时我们就需要手动导入环境变量了,可以在代码里执行如下操作。

<code class="">from dotenv import load_ dotenv
dotenv_ path = os. path. join( os. path. dirname(__ file__), '.env')
if os. path. exists( dotenv_ path): 
    load_ dotenv( dotenv_ path)

from bluelog import create_ app 
app = create_ app(' production')
</code>

使用 Gunicorn 运行程序

首先使用 pipenv 安装 gunicorn

<code class="">pipenv install gunicorn
</code>

然后我们就可以根据启动的文件名来启动 gunicorn

<code class="">gunicorn -w 4 -b 0.0.0.0:8000 kaki:app
</code>

其中-w 是多线程数的意思,上述就是开了4条线程,一般推荐开 CPU 核数*2+1的线程

使用 Nginx 提供反向代理

一般我们不直接使用gunicorn,而是使用一个常规的 web 服务器运行在前端,为 WSGI 服务器提供方向代理 使用 Nginx 的好处有如下几点

  • 提高处理静态文件的效率,Nginx 处理静态文件的速度非常快,而且可以对静态文件设置缓存。
  • 提高安全系数。可以避免直接暴露 WSGI 服务器,而且可以作为防火墙来防御网络攻击。
  • 提高程序处理能力。设置反向代理可以缓冲请求,对请求进行预处理,交给 WSGI 服务器一个完整的 HTTP 请求。还可以设置负载均衡,优化请求处理效率。

首先进行安装

<code class="">sudo yum install nginx
</code>

然后我们可以在/etc/nginx 文件夹里找到 nginx.conf 的配置文件,这里因为不具体讲解nginx,就直接用全局配置表了,更通用的做法是为某个项目建立独立的配置文件。这里直接给出Nginx 的 server 配置:

<code class="">server { 
        listen 80 default_ server; 
        server_ name _; # 如果 你 映射 了 域名, 那么 可以 写在 这里
        access_ log /var/ log/ nginx/ access. log; 
        error_ log /var/ log/ nginx/ error. log;
        location / {
        proxy_ pass http:// 127. 0. 0. 1: 8000; # 转发 的 地址, 即 Gunicorn 运行 的 地址 
        proxy_ redirect off; 
        proxy_ set_ header Host $ host;
        proxy_ set_ header X- Real- IP $ remote_ addr; 
        proxy_ set_ header X- Forwarded- For $ proxy_ add_ x_ forwarded_ for;
        proxy_ set_ header X- Forwarded- Proto $ scheme;
        }
        location /static { # 处理 静态 文件夹 中的 静态 文件
        alias /home/ greyli/ bluelog/ bluelog/ static/;
        expires 30d;  # 设置 缓存 过期 时间 
        }
}
</code>

这里只是简单的示例,具体里面的一些目录或者域名等参数设置,还得看具体的项目来定。 更新配置文件之后,我们可以通过下面的命令来测试语法的正确性:

<code class="">sudo index -t
</code>

如果一切正常,我们就重启 Nginx

<code class="">sudo service nginx restart
</code>

因为用了 Nginx 作方向代理,所以我们可以不用再设置 gunicorn 的 主机地址和端口,所以

<code class="">gunicorn -w 4 kaki:app
</code>

使用Supervisor 管理进程

前面我们直接用 Gunicorn 命令来运行,这样不可靠,我们需要一个自动化的工具。supervisor 可以通过自动化管理整个进程,包括重启等。 首先安装 Supervisor

<code class="">sudo yum install supervisor
</code>

测试是否安装成功

<code class="">echo_supervisord_conf
</code>

创建配置文件

<code class="">mkdir -p /etc/supervisor
mkdir -m 755 -p /etc/supervisor/
echo_supervisord_conf > /etc/supervisord.conf   #生成默认配置文件
sed -i "s/\;\[include\]/\[include\]/" /etc/supervisord.conf 
echo "files = /etc/supervisor/*.conf" >> /etc/supervisord.conf
</code>

然后我们在里面创建相应的 program 信息

<code class="">[program: bluelog]
command= pipenv run gunicorn -w 4 wsgi: app
directory=/ home/ greyli/ bluelog 
user= greyli 
autostart= true
autorestart= true
stopasgroup= true 
killasgroup= true
</code>

同样这里是示例,具体根据项目来调整。

  • 通过[ program] 定义 一个 bluelog 程序, 其中 用 command 定义 命令, 我们 在 命令 前 添加 pipenv run 以便 在 虚拟 环境 中 执行 命令; directory 和 user 则 分别 用来 设置 执行 命令 的 工作 目录 和 用户; 通过 将 autostart 和 autorestart 设为 true 开启 自动 启动 和 自动 重 启; 将 stopasgroup 和 killasgroup 设为 true 则 会 确保 在 关闭 程序 时 停止 所有 相关 的 子 进程。

  • 我们 在 command 参数 定义 的 命令 中 调用 了 pipenv run 命令, 而 Pipenv 内部 使用 Click 调用 命令, 为了 让 Click 在 Unix 以及 Python3 环境 下 能够 正确处理 编码 问题, 我们 需要 将 环境 变量 LC_ ALL 和 LANG 设为 C. UTF- 8 或 en_ US. UTF- 8, 这可 以在 supervisord. conf 配置文件 中 写入:

  • 我们需要在[supervisord]节添加下面的定义:

    environment= LC_ ALL=’ en_ US. UTF- 8’, LANG=’ en_ US. UTF- 8’

然后重启

<code class="">sudo service supervisor restart
</code>

最后再讲讲更新部署

<code class="">git pull 拉取更新
sudo supervisorctl stop kaki
flask db upgrade
sudo supervisorctl start kaki
</code>

至此,整个部署流程就简单的过了一遍了。

Flask

iOS面试题

HTML/CSS 基础