安装flask
pip install flask
wsgi
在开始之前,我们先了解一下wsgi:
-
Python Web Server Gateway Interface,翻译过来时Python web服务器网关接口,实际上就是一种协议,我们的应用(Django,Flask)实现了WSGI,就可以配合实现了WSGI(uWSGI,gunicorn)的服务器工作了。
-
简单介绍一下使用wsgi的两种模式:
-
两级结构
-
在这种结构里,uWSGI作为服务器,它用到了HTTP协议以及wsgi协议,flask应用作为application,实现了wsgi协议。当有客户端发来请求,uWSGI接受请求,调用flask app得到相应,之后相应给客户端。
-
这里说一点,通常来说,Flask等web框架会自己附带一个wsgi服务器(这就是flask应用可以直接启动的原因),但是这只是在开发阶段用到的,在生产环境是不够用的,所以用到了uwsgi这个性能高的wsgi服务器。
-
如图所示:
-
-
三级结构
-
这种结构里,uWSGI作为中间件,它用到了uwsgi协议(与nginx通信),wsgi协议(调用Flask app)。当有客户端发来请求,nginx先做处理(静态资源是nginx的强项),无法处理的请求(uWSGI),最后的相应也是nginx回复给客户端的。
多了一层反向代理有什么好处?- 提高web server性能(uWSGI处理静态资源不如nginx;nginx会在收到一个完整的http请求后再转发给wWSGI)
- nginx可以做负载均衡(前提是有多个服务器)
- 保护了实际的web服务器(客户端是和nginx交互而不是uWSGI)
-
如图所示:
-
-
flask中的wsgi
flask中的wsgi是用第三方包werkzeug实现的。
-
首先,先向大家介绍一下什么是 werkzeug,Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等。
-
Flask 框架就是以 Werkzeug 为基础开发的,这也是我要解析一下 Werkzeug 底层的原因,因为我想知道 Flask 的实现逻辑以及底层控制。下面代码(官方文档代码)只是以 Werkzeug 创建一个简单的 Web 应用,然后以这个 Web 应用为例剖析请求的处理以及响应的产生过程。
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
@Request.application
def index(requests):
return Response("Hello World")
if __name__ == '__main__':
# 请求一旦到来,请求第三个参数方法
run_simple("localhost", 4000, index)
-
了解上面代码,就需要从main开始看起。发现其实就是调用了一个run_simple函数,然后直接调用我们上面创建的index请求响应函数并用Request.application进行装饰构成application对象。那么,最关键的就是run_simple函数了。通过源码简单查看,发现run_simple其实就是在满足默认参数(见下文代码块参数,直接跳过修改默认参数判断)下,直接继承调用的是HTTPServer进而追溯到请求处理器(不继续深挖)来处理新建的application对象。
-
# run_simple参数 def run_simple( hostname, port, application, use_reloader=False, use_debugger=False, use_evalex=True, extra_files=None, reloader_interval=1, reloader_type="auto", threaded=False, processes=1, request_handler=None, static_files=None, passthrough_errors=False, ssl_context=None, )
Flask使用:
利用flask创建一个最简单的web(hello world)
from flask import Flask
# 对Flask重命名
app = Flask(__name__)
# 创建请求响应函数
# 用装饰器来装饰路由
@app.route('/index')
def index():
return "Hello World"
if __name__ == '__main__':
# 运行Flask
app.run()
为什么这块直接调用run方法就能直接跑起来?进入run源码你会发现,在run方法中,它会直接from werkzeug.serving import run_simple
调用run_simple方法。上面我们也知道run_simple方法需要三个参数(run方法如果不传参数host和port直接使用默认值,也可以自己定义,而最后的application参数就是调用run方法的自身也就是app对象)
`调用run_simple方法。上面我们也知道run_simple方法需要三个参数(run方法如果不传参数host和port直接使用默认值,也可以自己定义,而最后的application参数就是调用run方法的自身也就是app对象)
至此,就是flask搭建web的一个流程及底层逻辑。