Flask | Python Web 基本概念

Posted by Haauleon on June 4, 2018

Web 服务器

当我们在浏览器地址栏内输入 URL 后:
步骤一:浏览器会先请求 DNS 服务器,获得请求站点的 IP 地址。
步骤二:然后浏览器发送一个 HTTP 请求给拥有该 IP 的主机。
步骤三:接着浏览器就会接收到服务器给返回的 HTTP 响应。
步骤四:浏览器经过渲染后,以一种较好的效果呈现给我们。

这个过程中,正是Web 服务器在幕后默默做贡献。

  简单来说,Web 服务器是运行在物理服务器上的一个程序,它永久地等待客户端(主要是浏览器,比如 Chrome,Firefox 等)发送请求。当收到请求之后,它会生成相应的响应并将其返回至客户端。Web 服务器通过 HTTP 协议与客户端通信,因此也被称为HTTP 服务器


Web 服务器的工作原理

一般可分成如下4个步骤:建立连接、请求过程、应答过程以及关闭连接。

建立连接:客户机通过 TCP/IP 协议建立到服务器的 TCP 连接。
请求过程:客户端向服务器发送 HTTP 协议请求包,请求服务器里的资源文档。
应答过程:服务器向客户机发送 HTTP 协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端。由客户端解释 HTML 文档,在客户端屏幕上渲染图形结果。
关闭连接:客户机与服务器断开。

  web 服务器的主要工作是根据 request 返回 response,但是实际中的 Web 服务器远远比上面示例的复杂的多,因为要考虑的因素实在是太多了,比如:

  • 缓存机制:讲一些经常被访问的页面缓存起来,提高响应速度;
  • 安全:防止黑客的各种攻击,比如 SYN Flood 攻击;
  • 并发处理:如何响应不同客户端同时发起的请求;
  • 日志:记录访问日至,方便做一些分析。

  目前在 UNIX 和 LINUX 平台下使用最广泛的免费 Web 服务器有Apache和 Nginx 。



Web 应用程序

  Web 服务器的主要工作是根据 Request 返回 Response,但很多时候 Response 并不是静态文件,因此需要有一个应用程序根据 Request 生成相应的 Response。这里的应用程序主要用来处理相关业务逻辑,读取或者更新数据库,根据不同 Request 返回相应的 Response。要注意的是,这里并不是由 Web 服务器本身来做这件事,它只负责 Http 协议层面和一些诸如并发处理,安全,日志等相关的事情。

  应用程序可以用各种语言编写(Java, PHP, Python, Ruby等),这个应用程序会从 Web 服务器接收客户端的请求,处理完成后,再返回响应给 Web 服务器,最后由 Web 服务器返回给客户端。整个架构如下:



Web 框架

  早期开发站点做了许多重复性劳动,后来为了减少重复,避免写出庞杂、混乱的代码,人们将 Web 开发的关键性过程提取出来,开发出了各种 Web 框架。有了框架,就可以专注于编写清晰、易维护的代码,无需关心数据库连接之类的重复性工作。

  其中一种比较经典的Web框架采用了 MVC 架构,如下图所示:

  用户输入 URL,客户端发送请求,控制器(Controller)首先会拿到请求,然后用模型(Models)从数据库取出所有需要的数据,进行必要的处理,将处理后的结果发送给视图(View),视图利用获取到的数据,进行渲染生成 Html Response 返回给客户端。


  以 python web 框架 flask 为例,框架本身并不限定我们用哪种架构来组织我们的应用,不过 flask 可以很好地支持以 MVC 方式组织应用。

控制器:flask 可以用装饰器来添加路由项,如下:

1
2
3
@app.route('/')
def main_page():
    pass


模型:主要用来取出需要的数据,如下面函数中操作:

1
2
3
4
5
6
7
@app.route('/')
def main_page():
    """Searches the database for entries, then displays them."""
    db = get_db()
    cur = db.execute('select * from entries order by id desc')
    entries = cur.fetchall()
    return render_template('index.html', entries=entries)


视图:flask 利用 jinja2 来渲染页面,下面的模版文件指定了页面的样式:



Web 服务器网关接口

  Python 有着许多的 Web 框架,而同时又有着许多的 Web 服务器(Apache, Nginx, Gunicorn等),框架和 Web 服务器之间需要进行通信,如果在设计时它们之间是不可以相互匹配的,那么选择了一个框架就会限制对 Web 服务器的选择,这显然是不合理的。

  那么如何确保在不修改 Web 服务器代码或网络框架代码的前提下,使用自己选择的 Web 服务器,同时 Web 服务器又能匹配多个不同的网络框架呢?答案是接口,设计一套双方都遵守的接口就可以了。对 python 来说,就是 WSGI(Web Server Gateway Interface,Web服务器网关接口)。其他编程语言也拥有类似的接口:例如Java的Servlet API和Ruby的Rack。

  Python WSGI的出现,让开发者可以将 Web 框架与 Web 服务器的选择分隔开来,不再相互限制,从而根据自己的需求将不同的 Web 服务器与 Web 框架进行混合搭配。例如,可以使用 Gunicorn 或 Nginx/uWSGI 来运行 Django、Flask 或 web.py 应用。

  简单来说,WSGI 是连接 Web 服务器和 Web 应用程序的桥梁。一方面从 Web server 拿到原始 HTTP 数据,处理成统一格式后交给 Web 应用程序,另一方面从应用程序/框架这边进行业务逻辑处理,生成响应内容后交给服务器。