Linux-使用flask-uWSGI-nginx搭建mock-server
需求背景
需求产生
来了个新需求,公司产品系统和客户系统中的一个业务变动需要实时互相回传.涉及公司系统的接口只要进行接口测试接口.但是我们回传给客户的请求,就需要mock一个服务器在测试环境代替客户服务器.
需求分析
在网上搜寻了一番, 确认最后的技术架构为 flask + uWSGI+nginx, 使用云服务器作为server
- flask : 轻量级python web开发框架, 需要搭配web服务器使用(自带一个小型web服务器仅用于调试)
- uWSGI: 支持WSGI 和uwsgi 协议进行通讯的web服务器, 如果想要通过http外部访问需要通过反向代理服务器
- nginx : 反向代理服务器, 外部访问nginx,nginx再按照host转发给对应的服务器(可以实现负载均衡,服务器ip隐藏,静态文件返回,但我们这里主要用来实现web请求从http协议到uwsgi协议的转换)
购买云服务器
到腾讯云,阿里云或者华为云购买
推荐配置: 2C4M ,CentOS 7.6系统
腾讯云只要120RMB/year,香爆了
virtualenv
安装virtualenv
pip install virtualenv
pip install virtualenvwarpper
环境变量配置
# 1. 创建目录存放虚拟变量
mkdir ~/.virtualenvs
# 2. 配置环境变量
vim ~/.bashrc
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
# 3.初始化环境变量
source ~/.bashrc
# 测试命令是否被识别
workon
操作虚拟文件夹
一个虚拟文件夹代表一个虚拟环境,在创建虚拟环境时需要指定python解释器
- 注意: 创建虚拟环境时,需要指定解释器为Python3
workon #查看服务器内所有虚拟环境文件夹列表(与当前所处哪个目录无关)
mkvirtualenv -p python3 mock-server # 创建名为mock-server的虚拟环境,使用python3解释器
mkvirtualenv test # 创建名为test的虚拟环境文件夹,默认使用pyhton2解释器(注意:我们一般不用这个)
rmvirtualenv test #删除名为test的虚拟环境
workon mock-server # 进入mock-server虚拟环境
deactivate # 退出当前环境
其他常用命令
虚拟环境配置导入
pip freeze # 查看当前虚拟环境扩展
pip freeze > requirement.txt # 导出当前扩展信息
pip install -r requirement.txt # 从文件中安装所需软件
flask
在虚拟环境中安装flask
pip install flask
测试flask
编写test.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'hello world!'
if __name__=='__main__':
app.run() # 创建一个本地部署服务器用于访问(仅用于调试), 默认地址 localhost:5000
运行端口 ,访问测试
python test.py # 开启flask自带的本地web服务器,仅局域网内可用
curl 127.0.0.1: 5000 # 返回hello world 则测试成功
uwsgi
安装
yum install python-devel # 安装依赖
pip3 install uwsgi
uwsgi --version # 查看uwsgi版本
uwsgi --python-version # 验证是否使用python3解释器
测试
编写测试测试文档uwsgi_test.py
def application(env, start_response):
start_response('200 OK',[('Content-Type', 'text/html')])
return [b'hello world']
启动uwsgi,测试端口是否打开
uwsgi --http :8000 --wsgi-file uwsgi_test.py # 命令输入后日志无error,最后一行显示spawned uWSGI worker 1,则开启成功
curl 127.0.0.1: 8000 # 回复hello world则成功
uwsgi+flask
为uwsgi添加配置文件
在虚拟环境项目根目录下新建config.ini, 后续uwsgi通过配置的wsgi-file找到flask框架文件,通过callable找到uwsgi对象,开启接口访问
vim config.ini
[uwsgi]
# 本处开启http端口用于测试,后续搭配nginx需要使用uwsgi通讯,切记要改成'socket=xxx'
http=127.0.0.1:5000
# 虚拟环境绝对路径; .virtualenvs是virtualenv存放虚拟环境固定的文件夹,venv为自己创建的虚拟环境名
virtualenv = /root/.virtualenvs/venv
# 执行的flask python文件
wsgi-file = /root/others/virtualenv/flask_uwsgi/app.py
# uwsgi启用的application变量名,需要python文件中的Flask变量名保持一致
callable = app
# 开启进程数
processes = 2
# 开启线程数
threads = 8
buffer-size = 32768
# 允许主线程
master =true
flask文件准备
创建uwsgi.ini中配置的python文件(这里是app.py)
from flask import Flask
app = Flask(__name__) # 新建一个wsgi对象,此处变量名要和config.ini
@app.route("/api/test", methods=['POST'], strict_slashes=False)
def api_test():
print("start")
return "post success"
测试
开启服务
uwsgi config.ini # 出现woker则成功,则服务器开启成功
访问
curl -X POST 127.0.0.1:5000/api/test # 成功传回post success则访问成功
其他常用命令
ctrl + c # 方法1 : 在运行窗口关闭
pkill -f uwsgi -9 # 方法2: 按照进程名关闭进程
Nginx
安装
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel # 一键安装依赖
# 下载解压
wget http://nginx.org/download/nginx-1.14.2.tar.gz
tar zxvf nginx-1.14.2.tar.gz
# 进行编译和安装
cd nginx-1.14.2/
./configure
make && make install
修改配置
找到配置文件
ls /user/local/nginx/conf/ # 若安装成功,此处会自动生成nginx.conf文件
vim /usr/local/nginx/conf/nginx.conf
修改nginx配置
nginx将监听配置中的的server_name地址和listen端口,并将发送到的请求按照location内设置的协议及通讯地址,转发给对应服务器
# 配置当前用户名及log地址
user root;
error_log /var/log/nginx/error.log;
...
http {
server {
# 监听端口
listen 80;
# 监听地址 (可以是网址,也可以是ip地址)
server_name localhost;
# location后边的 "/" 表示匹配满足 localhost:80/* 所有的请求
location / {
# 使用uwsgi协议将请求传递给127.0.0.1:5000
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
}
修改uwsgi通讯协议
打开uwsgi配置文件config.ini
socket : 127.0.0.1:5000 # 搭配nginx不能使用http
测试
开启uwsgi及nginx
uwsgi config.ini
nginx # 开启nginx服务器
访问
curl -X POST localhost:80/api/test # 显示post success,则本地访问nginx成功
postman使用post方法访问 ${服务器ip}:80/api/test, 显示”post success”,则外部访问nginx成功!!!!
其他常用操作
killall -3 nginx # 关闭nginx
killall -1 nginx #重启nginx
根据需求完善架构
请求数据处理及保存
通过之前的操作,我们已经可以完成外部访问请求,并发送响应数据,接下来就需要对需求进行处理
- 通过request拿到响应数据,后续等到开发给到文档,就可以根据请求的不同return不同的响应结果
- 通过加入日志模块,将响应数据写入到日志中,用于测试请求数据是否正确
- 后续通过 tail flask.log -f -n 10实时查看请求信息
from flask import Flask,jsonify
import json
from flask import request
app = Flask(__name__)
# 加入日志模块
import logging
from logging import FileHandler
# 初始化logger
app.debug = True
handler = logging.FileHandler('flask.log')
app.logger.addHandler(handler)
@app.route("/api/ticket/status", methods=['PUT'], strict_slashes=False)
def api_test3():
# 获取请求体数据
data = request.get_json()
# 通过logger将json数据导出至flask.log文件夹
app.logger.info("<Request>url={url}, body={body}".format(url=request.url, body=json.dumps(data)))
return jsonify({"msg": "success ", "code": 0})
总结
做到这里框架基本搭建完毕了,请求访问流程图如下, 后边和开发对齐一下,完善一下flask接口文件就可以开始测试了.
此次搭建任务的重点,在于理清框架之间的关系,以及配置文件中重要配置项的含义.在我搭建过程中就因为找到了垃圾教程导致了配置错误导致访问失败,浪费了我1天时间解决问题.后续贴上我遇到的坑还有参考文档,共勉!
坑
大坑1:
在搭配nginx进行使用时,因为没有修改配置文件中的http为socket耽误了好长时间.
经过反思和总结:是因为学习过程中教程无法满足需要,频繁更换,降低了学习质量
在学习一门新技术时,一个好的教程非常重要,综合以下2个方面进行筛选:
教程与自己的设定目标的契合度:
如自己使用的是云服务器,centos系统, 而找的第一个教程用的是ubuntu,涉及很多页面UI操作,而导致最终放弃教程.
找到教程时,整体先确认先确认一下技术框架是否符合目标,部分符合目标的教程可以作为参照文档查看,但一定要找的一个全流程的教程文档,才可开始操作
教程的质量:
一门复杂新技术,照着教程一个代码一个代码敲掉进坑里几乎是必然的.一个好的教程,不只会记录如何操作,更会解释为什么.如果发现教程里面只有操作,没有解释,直接关掉
坑2:
使用uwsgi运行app.py时, 日志报空格错误 :
*** Operational MODE: preforking+threaded ***
File "/root/others/virtualenv/mock-server/app.py", line 15
return "post success"
^
TabError: inconsistent use of tabs and spaces in indentation
看似空格实则没有空格引起的, 如下图1即为异常区域,
解决: 删除空格,重新输入空格,重新尝试
参考文档:
flask + nginx + uWSGI部署(csdn难得的高质量博客,这是对我帮助最大的教程)
如何在 CentOS 上部署 Flask - 简书 (jianshu.com)(这篇主要讲的是virtualenv)
uWSGI+Nginx部署Python项目,服务器配置+生产环境配置_哔哩哔哩_bilibili
安装uwsgi 报错问题解决-云社区-华为云 (huaweicloud.com)
[(56条消息) ubuntu]安装virtualenv,virtualenvwrapper出错_Mata_Gao的博客-CSDN博客