-
系列其余内容
- docker 疾速创立轻量级的可移植的容器 ✓
- docker&flask 疾速构建服务接口 ✓
- docker&uwsgi 高性能 WSGI 服务器生产部署必备
- docker&gunicorn 高性能 WSGI 服务器生产部署必备
- docker&nginx&gunicorn 实现负载平衡
- docker&ngxtop 并实时解析 nginx 日志
- docker&supervisor 监控你的服务
- docker&pyinstaller 两步法构建小体积容器
- locust 对你的服务做高并发测试
- postman 热门的 API 调试工具
环境依赖
- 本教程是基于 redhat linux 服务器的
python: 3.8.3
click==8.0.1
Flask==2.0.1
Flask-Limiter==1.4
itsdangerous==2.0.1
Jinja2==3.0.1
limits==1.5.1
MarkupSafe==2.0.1
six==1.16.0
Werkzeug==2.0.1
WTForms==2.3.3
-
本文次要内容
- 包含 docker 部署 flask 服务、文件夹挂载、设置 flask 日志、设置参数验证局部、设置固定 ip 的申请次数限度、设置 ip 白名单。
docker&flask 创立容器
-
python 文件
- 设置 debug=True,当文件更新时,服务会主动重启
import flask, json
from flask import request
import platform
# 创立一个服务,把以后这个 python 文件当做一个服务
app = flask.Flask(__name__)
@app.route('/test', methods=['get'])
def login():
username = request.values.get('name')
pwd = request.values.get('pwd')
system = platform.system()
systemnode = platform.node()
system_info = "平台是 {0} & 运行节点是 {1}".format(system, systemnode)
if username and pwd:
if username=='xiaoming' and pwd=='111':
resu = {'code': 200, 'message': '登录胜利', 'system':system_info}
return json.dumps(resu, ensure_ascii=False)
else:
resu = {'code': -1, 'message': '账号密码谬误', 'system':system_info}
return json.dumps(resu, ensure_ascii=False)
else:
resu = {'code': 10001, 'message': '参数不能为空', 'system':system_info}
return json.dumps(resu, ensure_ascii=False)
if __name__ == '__main__':
app.run(debug=True, port=2222, host="0.0.0.0")
- Dockerfile 文件
FROM python:3.8
WORKDIR /home/myfirstapi/
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY . .
RUN pip install -r requirements.txt -q -i https://pypi.tuna.tsinghua.edu.cn/simple && \
rm -rf /var/cache/apk/*
expose 2222
CMD ["python3", "flask_test.py"]
-
为了测试不便咱们特意设置
- python 脚本中 debug=True,当脚本更新时服务主动重启
- docker 容器设置数据卷,使本地的更改能够主动同步到容器中。
# 构建名称为 test/dockerflask,版本为 1.0 的镜像
docker build -t test/dockerflask:1.0 .
# 通过镜像 test/api 创立一个后盾运行的容器,且映射端口 2222, 将本地文件夹 /root/first_api/flask_api 挂载到容器指定目录下
docker run -d -p 2222:2222 --name docker_flask_api -v /root/first_api/flask_api:/home/myfirstapi/ test/dockerflask:1.0
- 失去后果如下:
flask 设置日志
-
能够参考 python 的 logger 库
def login(): ... app.logger.debug('this is a DEBUG message') app.logger.info('this is an INFO message') app.logger.warning('this is a WARNING message') app.logger.error('this is an ERROR message') app.logger.critical('this is a CRITICAL message')
- 失去后果如下
flask 减少参数验证局部
-
设置验证局部
from wtforms.fields import simple from wtforms import Form, StringField, IntegerField from wtforms.validators import Length, Regexp, NumberRange, AnyOf, DataRequired class parameters_validation(Form): username = StringField(validators=[AnyOf(values = ["xiaoming", "laolitou"])]) pwd = StringField(validators = [DataRequired() Length(max=4,min=2,message="the length of the pwd must between %(min)d and %(max)d"), Regexp(regex="\d+",message="pwd must be start with numbers")], ) @app.route('/test', methods=['get']) def login(): form = parameters_validation(request.args) if form.validate(): username = form.username.data pwd = form.pwd.data ... else: return jsonify(form.errors) if __name__ == '__main__': app.run(debug=True, port=2222, host="0.0.0.0")
- 失去后果如下
flask 减少 ip 限度局部
-
flask 设置 ip 拜访次数
from flask import Flask from flask_limiter import Limiter from flask_limiter.util import get_remote_address app = Flask(__name__) limiter = Limiter( app, key_func=get_remote_address, default_limits=["5 per day", "2 per hour"] ) @app.route("/1times") @limiter.limit("1 per day") def slow(): return "每天只能拜访 1 次" @app.route("/2times") def fast(): return "每天能拜访 5 次,一小时内只能拜访 2 次" @app.route("/nolimits") @limiter.exempt # 无拜访速率限度 def ping(): return "拜访无次数限度呀" if __name__ == '__main__': app.run(debug=True, port=2222, host="0.0.0.0")
-
失去后果如下
- 有了这个,对外提供给包月服务的话,这个是不是就能够很容易的加上服务次数的限度了啦
- 有了这个,对外提供给包月服务的话,这个是不是就能够很容易的加上服务次数的限度了啦
flask 设置 ip 白名单
- flask 设置 ip 白名单,只针对局部 ip 提供服务
from flask import abort, Flask, render_template, request
ALLOWED_IPS = ['10.92', '10.91']
app = Flask(__name__)
@app.errorhandler(403)
def permission_error(e):
return "没权限呀没权限呀呈现了 403 谬误: %s"%e
@app.before_request
def limit_remote_addr():
client_ip = str(request.remote_addr)
valid = False
for ip in ALLOWED_IPS:
if client_ip.startswith(ip) or client_ip == ip:
valid = True
break
if not valid:
abort(403)
@app.route('/', methods = ['GET'])
def home():
return "Your IP: {}".format(request.remote_addr)
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
- 失去如下后果
后续
- 一般而言,咱们正式提供一个服务是须要做负载平衡的,毕竟要思考用户的应用体验;
- 在 nginx 做负载平衡的过程中,申请限度,ip 白名单也都是能够配置的。