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 &让服务在后台运行,或者挂一个 screen screen -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__.pyapp 工厂函数,根据不同环境配置初始化 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 虚拟环境
  • ……

最后#

在搭建项目的时候根据自己项目实际情况,选择合适的架构才是正确的选择。

参考文献#

Flask 的架构升级
https://www.waterwater.moe/posts/2018/2018-01-13_flask的架构升级/
作者
whitewater
发布于
2018-01-13
许可协议
CC BY-NC-SA 4.0