804 字
4 分钟
Flask 的架构升级
渐进式搭建大型 Flask 应用
hello world
- 第一个 flask 应用(这个示例程序还需要
templates
文件夹存放模板)
# manage.py
#!/usr/bin/python
# -*- coding:utf-8 -*-
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/hello_world')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
使用python manage.py
可以快速启动服务,但这种服务启动方式只适合开发环境测试,因为存在以下几个问题。
- flask 的自带服务器不支持多线程,用于多人的环境时很容易发生阻塞
- 服务因意外崩溃时不会自动重启
- 一旦你的 shell 关闭,你的服务将被停止。可以使用
nohup python manage.py &
让服务在后台运行,或者挂一个 screenscreen -S pythonServer``python manage.py
(这些方案只适用于快速搭建服务,生产环境应该使用服务器)
扩展
随着功能的增加,必须根据不同功能把程序拆分成文件,使用manage.py
作为入口,在views.py
处理路由,在errors.py
中处理错误。项目结构修改为这样:
proj
│ manage.py # 应用入口
│
├─app
│ errors.py # 错误处理
│ utils.py # 工具类
│ views.py # 视图/路由
│ __init__.py
│
├─templates # 模板文件夹
│ about.html
│ index.html
│ login.html
│
└─static # 静态资源
app.js
app.css
查缺补漏
- 服务器 在生产环境使用 web 服务器。如 Nginx, Gunicorn, Tornado
- 管理服务 使用
supervisor
,systemd
等方式保证服务可靠运行 - 日志 为了快速定位 bug 以及溯源异常信息,需要使用日志模块输出日志而不是简单地使用
print('errorInfo')
这种方式 debug, 常用的日志模块有log4j
等 - 配置文件 方便切换开发环境和生产环境配置
- 测试
- 版本控制 开发必备,不多说,使用
Git
吧,还建议使用贴近项目的工作流Git 工作流程
更大、更复杂
利用蓝图和 flask 强大的扩展能力,创建更大的项目
proj
│-app/
│-templates/
│-static/
│-main/
│-__init__.py
│-errors.py
│-forms.py
│-views.py
│-auth/
│-__init__.py
│-forms.py
│-views.py
│-__init__.py
│-email.py
│-models.py
│-migrations/
│-tests/
│-__init__.py
│-test*.py
│-venv/
│-requirements.txt
│-config.py
│-manage.py
应用细节
manage.py
主入口
#!/usr/bin/python
# -*- coding:utf-8 -*-
import os
from app import create_app
# 配置
config_name = os.getenv('FLASK_CONFIG') or 'default'
app = create_app(config_name)
# gunicorn -k gevent -w 8 -b 127.0.0.1:5000 manage:app
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000, debug=True)
config.py
配置文件
# -*- coding:utf-8 -*-
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite://:memory:'
@staticmethod
def init_app(app):
pass
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
config={
'dev':DevelopmentConfig,
'test':TestingConfig,
'prod':ProductionConfig,
'default':DevelopmentConfig
}
app/__init__.py
app 工厂函数,根据不同环境配置初始化 app
#!/usr/bin/python
# -*- coding:utf-8 -*-
from flask import Flask
from config import config
def create_app(config_name):
app=Flask(__name__)
# 加载配置
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# 注册蓝图
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
app.logger.debug('应用初始化完成') # DEBUG
return app
app/main/__init__.py
蓝图
# -*- coding:utf-8 -*-
from flask import Blueprint
main = Blueprint('main', __name__)
app/main/views.py
蓝图的视图
# -*- coding:utf-8 -*-
from flask import current_app as app
from . import main
# 测试接口
@main.route('/')
def index():
app.logger.debug('SUCCESS') # DEBUG
return 'Hello'
其他
- 前后端分离
- 缓存
- 权限管理
- 访客分析
- 服务器监控
- 负载均衡
- CDN
- 分布式
- CICD
- Python venv 虚拟环境
- ……
最后
在搭建项目的时候根据自己项目实际情况,选择合适的架构才是正确的选择。