天天看点

从零开始搭建论坛(一):Web服务器与Web框架

【引自selfboot的博客】之前用 django 做过一个小的站点,感觉django太过笨重,于是就准备换一个比较轻量级的 web

框架来玩玩。web.py 作者已经挂掉,项目好久没有更新,所以不准备用它。而 flask 也是一个成熟的轻量级 web 框架,在 github

上有众多的 star 和 fork,文档和扩展也很丰富,值得学习。

从零开始搭建论坛(一):Web服务器与Web框架

论坛系统截图

下面是论坛的基本功能:

完整的用户模块(注册、登录,更改、找回密码、信息修改、站内消息通知);

丰富的论坛模块(创建、回复话题,站内搜索,markdown支持,@user 提醒);

强大的后台管理,支持屏蔽用户、话题、评论,支持各种条件搜索话题、评论;

本博客将会用一系列文章,记录论坛系统搭建的过程,希望对刚入门web开发的同学有所帮助。

我们经常听说 django, flask 这些 python 语言的web

框架,那么框架到底是什么,web框架和web服务器(nginx, apache等)有什么区别?离开框架还能用 python

搭建web站点吗?要解决这些疑问,我们有必要来理解下 web 服务器的工作原理,以及 web 框架的本质。

web 服务器

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

从零开始搭建论坛(一):Web服务器与Web框架

 web 服务器

web服务器的工作原理并不复杂,一般可分成如下4个步骤:建立连接、请求过程、应答过程以及关闭连接。

建立连接:客户机通过tcp/ip协议建立到服务器的tcp连接。

请求过程:客户端向服务器发送http协议请求包,请求服务器里的资源文档。

应答过程:服务器向客户机发送http协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端。由客户端解释html文档,在客户端屏幕上渲染图形结果。

关闭连接:客户机与服务器断开。

下面我们实现一个简单的 web 服务器。运行示例程序后,会监听本地端口 8000,在浏览器访问 http://localhost:8000 就能看到响应内容。而我们的程序也能够打印出客户端发来的请求内容,如下图:

从零开始搭建论坛(一):Web服务器与Web框架

 简单web服务器

这里request 和 response 都需要遵守 http 协议,关于 http 协议的详细内容,可以读读《http 权威指南》,或者看我整理的http 部分内容。

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

缓存机制:讲一些经常被访问的页面缓存起来,提高响应速度;

安全:防止黑客的各种攻击,比如 syn flood 攻击;

并发处理:如何响应不同客户端同时发起的请求;

日志:记录访问日至,方便做一些分析。

目前在unix和linux平台下使用最广泛的免费 web 服务器有apache和 nginx 。

web 应用程序

web 服务器接受 http request,返回 response,很多时候 response

并不是静态文件,因此需要有一个应用程序根据 request 生成相应的

response。这里的应用程序主要用来处理相关业务逻辑,读取或者更新数据库,根据不同 request 返回相应的

response。注意这里并不是 web 服务器本身来做这件事,它只负责 http 协议层面和一些诸如并发处理,安全,日志等相关的事情。

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

从零开始搭建论坛(一):Web服务器与Web框架

 web应用程序

以 python 为例,使用python开发web,最原始和直接的办法是使用cgi标准,在1998年这种方式很流行。首先确保 web

服务器支持cgi及已经配置了cgi的处理程序,然后设置好cgi目录,在目录里面添加相应的 python 文件,每一个 python

文件处理相应输入,生成一个 html 文件即可,如下例:

# !/usr/bin/python 

# -*- coding: utf-8 -*- 

print "content-type:text/html" 

print  # 空行,告诉服务器结束头部 

print '<html>' 

print '<head>' 

print '<meta charset="utf-8">' 

print '</head>' 

print '<body>' 

print '<h2>hello word! 我是一个cgi程序</h2>' 

print '</body>' 

print '</html>'  

这样在浏览器访问该文件就可以得到一个简单的 hello world 网页内容。直接通过 cgi 写 web 应用程序看起来很简单,每一个文件处理输入,生成html。但是实际开发中,可能会遇到许多不方便的地方。比如:

每个独立的cgi脚本可能会重复写数据库连接,关闭的代码;

后端开发者会看到一堆 content-type 等和自己无关的 html 页面元素;

web 框架

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

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

从零开始搭建论坛(一):Web服务器与Web框架

 mvc 架构

用户输入

url,客户端发送请求,控制器(controller)首先会拿到请求,然后用模型(models)从数据库取出所有需要的数据,进行必要的处理,将处理后的结果发送给

视图(view),视图利用获取到的数据,进行渲染生成 html response返回给客户端。

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

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

@app.route('/') 

def main_page(): 

    pass  

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

    """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 来渲染页面,下面的模版文件指定了页面的样式:

{% for entry in entries %} 

<li> 

  <h2>{{ entry.title }}</h2> 

  <div>{{ entry.text|safe }}</div> 

</li> 

{% else %} 

<li><em>no entries yet. add some!</em></li> 

{% endfor %}  

web 服务器网关接口

我们知道python有着许多的 web 框架,而同时又有着许多的 web 服务器(apache, nginx,

gunicorn等),框架和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应用。

从零开始搭建论坛(一):Web服务器与Web框架

 wsgi 适配

下一篇我们将会仔细分析 wsgi 接口标准,然后一起来写一个简单的 wsgi web 服务器。

作者:selfboot

来源:51cto