1.蓝图
a.代码模块化,不同功能的模块,划分成不同的分类,降低各功能之间的耦合度b.蓝图:用于实现单个应用的视图、模板、静态文件的集合。c.蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和URL相互关联的功能复制代码
2.蓝图实例
user.py文件
from flask import Blueprint# 创建蓝图users = Blueprint('user',__name__)@users.route('/user')def user(): return "User Page"复制代码
login.py文件
from flask import Flask,Blueprint# 创建蓝图logins = Blueprint('login',__name__)@logins.route('/login')def login(): return "Login Page"复制代码
主文件:
from flask import Flask# 导入蓝图对象from login import loginsfrom user import usersapp = Flask(__name__)@app.route('/')def hello_world(): return "Hello World!"#注册蓝图,第一个参数logins是蓝图对象,url_prefix参数默认值是根路由,如果指定,会在蓝图注册的路由url中添加前缀。app.register_blueprint(logins,url_prefix='/')app.register_blueprint(users,url_prefix='/')if __name__ == '__main__': print(app.url_map) app.run(debug=True)复制代码
3.部署
部署方式:nginx+gunicorn+flask
wsgi协议:一种通信协议,连接web服务器和web应用框架
uwsgi协议
uWSGI:实现上述两种协议的web服务器
1.安装gunicorn :pip install gunicorn
指定进程和端口号: -w: 表示进程(worker)。 -b:表示绑定ip地址和端口号(bind)
命令:gunicorn -w 4 -b 127.0.0.1:5001 运行文件名称:Flask程序实例名
4.RESTFUL风格
a.REST是设计风格而不是标准。是指客户端和服务器的交互形式。我们需要关注的重点是如何设计REST风格的网络接口b.REST特点: 具象的:一般指表现层,要表现的对象就是资源。比如,客户端访问服务器,获取的数据就是资源。比如文字、图片、音视频等 表现:资源的表现形式。txt格式、html格式、json格式、jpg格式等。浏览器通过URL确定资源的位置,但是需要在HTTP请求头中,用Accept和Content-Type字段指定,这两个字段是对资源表现的描述。 状态转换:客户端和服务器交互的过程。在这个过程中,一定会有数据和状态的转化,这种转化叫做状态转换。其中,GET表示获取资源,POST表示新建资源,PUT表示更新资源,DELETE表示删除资源。HTTP协议中最常用的就是这四种操作方式。c.RESTFul架构每个URL代表一种资源;客户端和服务器之间,传递这种资源的某种表现层;客户端通过四个http动词,对服务器资源进行操作,实现表现层状态转换。复制代码
ps:1 每个URL代表一种资源,2. get post delete put分别代表增删改查 3 看URL就能知道代表那种资源
5.怎样设计符合RESTful风格的API
a.域名将api部署在专用域名下:http://www.example.com/api/b.版本将API的版本号放在url中:http://www.example.com/app/1.0/infoc.路径路径表示API的具体网址。每个网址代表一种资源。 资源作为网址,网址中不能有动词只能有名词,一般名词要与数据库的表名对应。而且名词要使用复数。错误实例:http://www.example.com/getGoodshttp://www.example.com/listOrders正确示例:#获取单个商品http://www.example.com/app/goods/1#获取所有商品http://www.example.com/app/goodsd.使用标准的HTTP方法GET SELECT :从服务器获取资源。POST CREATE :在服务器新建资源。PUT UPDATE :在服务器更新资源。DELETE DELETE :从服务器删除资源。示例:#获取指定商品的信息GET http://www.example.com/goods/ID#新建商品的信息POST http://www.example.com/goods#更新指定商品的信息PUT http://www.example.com/goods/ID#删除指定商品的信息DELETE http://www.example.com/goods/IDe.过滤信息如果资源数据较多,服务器不能将所有数据一次全部返回给客户端。API应该提供参数,过滤返回结果。#指定返回数据的数量http://www.example.com/goods?limit=10#指定返回数据的开始位置http://www.example.com/goods?offset=10#指定第几页,以及每页数据的数量http://www.example.com/goods?page=2&per_page=20f.状态码服务器向用户返回的状态码和提示信息,常用的有:200 OK :服务器成功返回用户请求的数据201 CREATED :用户新建或修改数据成功。202 Accepted:表示请求已进入后台排队。400 INVALID REQUEST :用户发出的请求有错误。401 Unauthorized :用户没有权限。403 Forbidden :访问被禁止。404 NOT FOUND :请求针对的是不存在的记录。406 Not Acceptable :用户请求的的格式不正确。500 INTERNAL SERVER ERROR :服务器发生错误。g.错误信息一般来说,服务器返回的错误信息,以键值对的形式返回{ error:'Invalid API KEY'}h.响应结果i.其他服务器返回的数据格式,应该尽量使用JSON,避免使用XML复制代码
6.性能
服务端性能优化:1.使用缓存加速数据读取(大量访问的数据,存储在读写效率比较高的介质中,比如 redis)2.使用集群提高数据吞吐能力3.使用异步消息加快请求响应4.使用代码改善程序性能(多线程)问题:如果访问首页被设置成了缓存,但是缓存都有过期时间,如果在缓存没有过期的时候,首页内容被更改,缓存没有更改,导致我们看到的内容还是之前的,这个怎么解决?答:1.设置尽量少的过期时间 2.每次修改更新了数据库,都要同步更新缓存复制代码
7.flask中添加日志信息
rom flask import Flaskimport loggingapp = Flask(__name__)# 日志系统配置handler = logging.FileHandler('app.log', encoding='UTF-8')logging_format = logging.Formatter( '%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')handler.setFormatter(logging_format)app.logger.addHandler(handler)@app.route('/')def index(): try: no_thing = [] app.logger.info('info log') app.logger.warning('warning log') i = no_thing[0] # 这里会报错,因为列表根本是空的 return 'Hello!' except Exception as e: app.logger.error('%s', e)if __name__ == '__main__': app.run(port=8802,debug=True)复制代码
ERROR:这个级别的日志意味着系统中发生了非常严重的问题,必须有人马上处理,比如数据库不可用了,系统的关键业务流程走不下去了等等。很多人在实际开发的时候,不会去区分问题的重要程度,只要有问题就error记录下来,其实这样是非常不负责任的,因为对于成熟的系统,都会有一套完整的报错机制,那这个错误信息什么时候需要发出来,很多都是依据单位时间内error日志的数量来确定的。因此如果我们不分轻重缓急,一律error对待,就会徒增报错的频率,久而久之,我们的救火队员对错误警报就不会那么在意,这个警报也就失去了原始的意义。WARN:发生这个级别的问题时,处理过程可以继续,但必须要对这个问题给予额外的关注。假设我们现在有一个系统,希望用户每一个月更换一次密码,而到期后,如果用户没有更新密码我们还要让用户可以继续登录,这种情况下,我们在记录日志时就需要使用WARN级别了,也就是允许这种情况存在,但必须及时做跟踪检查。INFO:这个级别的日志我们用的也是比较多,它一般的使用场景是重要的业务处理已经结束,我们通过这些INFO级别的日志信息,可以很快的了解应用正在做什么。我们以在12306上买火车票为例,对每一张票对应一个INFO信息描述“[who] booked ticket from [where] to [where]”。DEBUG和TRACE:我们把这两个级别放在一起说,是应为这两个级别的日志是只限于开发人员使用的,用来在开发过程中进行调试,但是其实我们有时候很难将DEBUG和TRACE区分开来,一般情况下,我们使用DEBUG足以。app.logger.debug('A value for debugging')app.logger.warning('A warning occurred (%d apples)', 42)app.logger.error('An error occurred')复制代码
8.部署之gevent+celery
待总结复制代码
9.gunicorn和nginx部署
部署视频:https://www.bilibili.com/video/av45206566?from=search&seid=695331927454347708复制代码
1.gunicorn配置 安装gunincorn pip install gunicorn 启动flask命令:gunicorn -w (开启进程数) -b (服务器和端口) -D(表示以进程运行,后台不会关闭) --access-logfile ./logs/log 运行的程序:app
w:表示进程数 b:表示允许访问的ip和端口号 -D:是以进程的形式开启 --access-logfile 表示日志文件 运行的程序:表示主程序名 app:实例名
以配置文件开启:在主程序同级目录下新建配置文件,gun.cnf,配置如下:bind = '0.0.0.0:8802'workers = 10 proc_name = 'app'pidfile = '/tmp/app.pid'其中:workers表示开启10个进程gunicorn -c gun.conf face_app:app --reload -D (在服务器上的部署命令,flasktest表示全部接口的 那个py文件)复制代码
2.nginx
多台服务器配置在upstraem中,flask是自己命名的,nginx收到请求会转发到两台服务器上,找到下边的location,location中最后两行配置是客户端的原始信息,ip等原封不动的给到业务服务器