Flask基础-(部署)

864 阅读8分钟

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 logins
from user import users

app = 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/info
c.路径
路径表示API的具体网址。每个网址代表一种资源。 资源作为网址,网址中不能有动词只能有名词,一般名词要与数据库的表名对应。而且名词要使用复数。

错误实例:
http://www.example.com/getGoods
http://www.example.com/listOrders
正确示例:
#获取单个商品
http://www.example.com/app/goods/1
#获取所有商品
http://www.example.com/app/goods

d.使用标准的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/ID

e.过滤信息
如果资源数据较多,服务器不能将所有数据一次全部返回给客户端。API应该提供参数,过滤返回结果。

#指定返回数据的数量
http://www.example.com/goods?limit=10
#指定返回数据的开始位置
http://www.example.com/goods?offset=10
#指定第几页,以及每页数据的数量
http://www.example.com/goods?page=2&per_page=20

f.状态码
服务器向用户返回的状态码和提示信息,常用的有:
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 Flask
import logging

app = 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等原封不动的给到业务服务器