本文主要介绍基于Flask与Nginx搭建一个简易的API系统,作为演示该系统只有一个后台API,接收来自前台的参数,然后返回生成的随机数。整个部署环境是Ubuntu18.04操作系统。

Flask是Python下一个轻量级Web应用框架,关键的优势在于:

  • 轻量级,简单够用;
  • 基于python,好上手;

Nginx与Flask搭配使用的架构图基本如下:

Nginx与Flask架构图

  • Nginx作为网络服务器,接收来自用户的请求,并将请求反向代理到Gunicorn服务器;
  • Gunicorn是一个运行Python Web应用程序的WSGI(Web 服务器网关接口)HTTP服务器;
  • supervisor是一个进程管理工具,可以监控gunicorn的运行情况,如果意外关机,可以自动重启;
  • Flask App就是我们开发的应用服务;

1、Flask App的开发:

要开发Flask App,首先安装python环境:

1.1 安装python虚拟环境

查看python3是否安装:

1
python3 --version

安装虚拟环境模块:

1
sudo apt install python3-venv

创建flask执行的虚拟环境:

1
python3 -m venv myflask

创建好后,进入myflask文件夹,运行如下命令激活虚拟环境:

1
source ./bin/activate

激活后,安装flask库:

1
pip3 install Flask
1.2 开发Flask App

类似C语言下的hello world,首页我们开发一个Flask下的hello world。完成1.1步骤,进入其中的 myflask目录;

创建如下名为app.py的python文件:

1
2
3
4
5
6
from flask import Flask
app=Flask(__name__)

@app.route('/')
def index():
return '<h1>Hello World! From Flask!</h1>'

编辑保存后,终端运行:

1
flask run

2024-03-26-flaskrun启动

根据终端的提示,用浏览器打开http://127.0.0.1:5000/即可看到输出:

2024-03-26-浏览器打开helloflask

仔细观察终端的输出,可以发现当前的开发环境是:production,而当前的访问端口是5000。

那如何修改这些配置呢?比如将production环境切换为development环境,把端口从5000修改8000等,此时需要使用环境变量。我们在当前开发目录下,创建.flaskenv环境变量文件:

1
2
3
FLASK_ENV=development ##设置为开发环境;
FLASK_APP=app.py ##如果你app名为app,可以不显示注明;如果不是,一定要显示注明。
FLASK_RUN_PORT=8000

那么flask怎么去读这个.flaskenv环境变量文件呢?还需要再安装python-dotenv这个python库:

1
pip3 install python-dotenv

然后,再次运行flask run:

2024-03-26-flaskenv环境变量

上图中可以发现已经处于开发模式,并且端口也切换到8000。

1.3 完善Flask App的返回随机数功能:

要返回随机数,来自客服端的关于随机数长度、字符数等请求信息,所以路由端的代码如下:

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
@app.route('/getrandomstr', methods=['POST'])
def getrandomstr():
if request.method == 'POST':
data_json=request.get_json()
#print(data_json)

##get parameters,获取来自客户端的信息;
intlen=data_json.get("intlen")
intnum=data_json.get("intnum")
withnum=data_json.get("withnum")
withlow=data_json.get("withlow")
withup=data_json.get("withup")
withspecial=data_json.get("withspecial")

##请求的随机数长度过长,数量过多则返回fail;
if intlen>30 or intnum >1000:
return jsonify(data=[], datalen=0, msg="fail")

strings=[]
##根据客户端信息调用生成随机数生成;
strings=generate_random_string(intlen, intnum, withnum, withlow, withup, withspecial)
datalen=len(strings)

if datalen>0:
return jsonify(data=strings, datalen=datalen, msg="success")
else:
return jsonify(data=[], datalen=0, msg="fail")

上述路由代码中,核心的随机字符串生成函数generate_random_string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def generate_random_string(length, num_strings, use_numbers, use_lower_case, use_upper_case, use_special_chars):
# Create a list of characters to choose from
chars = []
if use_numbers:
chars += [str(i) for i in range(10)]
if use_lower_case:
chars += [chr(i) for i in range(97, 123)]
if use_upper_case:
chars += [chr(i) for i in range(65, 91)]
if use_special_chars:
chars += ['!','@','#','$']

# Generate the strings
strings = []
for _ in range(num_strings):
string = ''
for _ in range(length):
string += random.choice(chars)
strings.append(string)

return strings

另外还需要引入必要的python库:

1
2
3
from flask import request
from flask import jsonify
import random

编写代码后,运行flask run看是否有出现错误,如果没有错误,接下来就需要来测试随机数端口,看是否可以根据客户端提供的参数返回对应的结果。

我们采用bruno软件来测试API接口:postman替代,轻量级、免费免安装的postman替代品Bruno (qq.com)比如测试hello接口:

2024-03-26-bruno测试gethello

测试随机数生成的接口:

2024-03-26-postbruno测试

说明现在的Flask App功能已经完善,剩下是生产环境部署。要部署,我们首先修改.flaskenv文件:

1
2
3
FLASK_ENV=production ##设置为生产环境;
FLASK_APP=app.py ##如果你app名为app,可以不显示注明;如果不是,一定要显示注明。
FLASK_RUN_PORT=5000 ##重新设置为5000端口

2. gunicorn的安装与使用

生产环境中,Flask自带的WSGI服务器不够用,我们需要使用更专业的服务器,比如gunicorn;

我们在python虚拟环境中,安装gunicorn:

1
pip3 install gunicorn

安装成功后,当前目录下运行gunicorn:

1
gunicorn -w 3 -b 0.0.0.0:5000 app:app
  • -w:表示开启三个进程, gunicorn 应该使用的工作进程数量。在这里,它设置为 3,意味着会有 3 个工作进程并行地处理请求,这有助于提高应用的吞吐量;

  • -b:表示接收所有ip访问,并且端口为5000;

  • -app:app:启动app(.py文件)模块中的app对象;

2024-03-26-gunicorn启动三个进程

如上图gunicorn开始启动运行,开了三个工作进程;再次使用bruno来测试post,注意端口是5000,发现可以正常的工作。

3. supervisor的安装与配置

对照我们的架构图,现在我们还需要安装一个supervisor,supervisor的主要作用是监控gunicorn的运行,万一gunicorn因为各种原因down机,supervisor可以自动重启gunicorn,保证生产环境的稳定性。

Nginx与Flask架构图

ubuntu下安装supervisor的命令如下:

1
sudo apt install supervisor

进入supervisor的配置文件夹,/etc/supervisor/conf.d/,创建名为”flaskrandom.conf”配置文件,主要内容如下:

1
2
3
4
5
6
7
8
[program:flaskrandom]
command=/home/tfzhang/myflask/bin/gunicorn -w 3 -b 0.0.0.0:5000 app:app
directory=/home/tfzhang/myflask/ ##app.py所在的目录;
user=tfzhang ##当前操作系统的用户名
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true

更新完”flaskrandom.conf”配置文件后,再输入如下两个命令:

1
2
sudo supervisorctl reread  ##重新读取配置文件;
sudo supervisorctl update ##使新配置文件生效;

查看当前supervisor监控的任务:

1
sudo supervisorctl

2024-03-26-supervisor基本操作

可以发现Flask App对应的进程已经运行,用浏览器或者bruno可以正常访问服务,说明supervisor配置正确。

假设现在意外重启Ubuntu,可以测试Flask App是否会随着机器的重启,而自动运行

要关闭app服务,则在supervisor终端:

1
2
sudo supervisorctl ##启动supervisor终端
supervisor > stop flaskrandom

如果要启动,则同样的:

1
supervisor > start flaskrandom

4. 配置Nginx的反向代理

生产环境中,不会直接使用gunicorn接收用户的请求,用户的请求首先到达Nginx,再由Nginx作反向代理,去访问gunicorn。

为什么需要将Nginx作反向代理?

  • Nginx功能更强大;
  • 安全:通过Nginx作内外隔离;

Ubuntu下安装Nginx的命令:

1
sudo apt install nginx

完成nginx安装后,配置nginx文件/etc/nginx/sites-available/default:

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
server {
listen 80 default_server;
listen [::]:80 default_server;

root /var/www/html;

# Add index.php to the list if you are using PHP
index index.html index.htm index.php index.nginx-debian.html;

server_name _;

location / {
proxy_pass http://127.0.0.1:5000/;
try_files $uri $uri/ =404;
}

# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
include snippets/fastcgi-php.conf;

# # With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
}

上述配置文件中,最重要的一句是:

1
proxy_pass http://127.0.0.1:5000/;

主要含义是将原来到”/“的访问重定向到”http://127.0.0.1:5000/",保存上述配置文件,然后重启nginx使得新配置生效:

1
sudo service nginx reload

我们再次测试时,可以发现不需要再在浏览器或者bruno中带5000端口号,就可以访问到Flask App的数据,说明nginx的反向代理发挥作用。

2024-03-26-nginx反向代理成功

5. 总结

上述我们所有的操作都是Ubuntu18.04系统上测试通过,由于是本地虚拟机,不能演示如何配置网站域名以及SSL证书,所以关于上线的内容大家可以直接去看其他关于Nginx如何上线的内容,这些内容与Flask App已经没有关系,完全只和Nginx有关。

到实际的云服务器环境,只要你选择的操作系统是Ubuntu18.04,上述操作可以复刻,唯一可能需要注意的地方是防火墙,开端口访问权相关的问题。

6 源代码:

app.py源代码位于gitee