以下代码可能有省略。
1. HTTP 基本原理
- 服务器上需要运行 web server 软件(下面以 nginx 为例,常见的还有 apache、lighttpd),nginx 以守护进程模式运行后,默认监听 tcp 的 80 端口,准备响应客户端的请求。
- 客户端(这里指浏览器)需要访问站点时,浏览器打开本地一个临时端口,主动向服务器上的 80 端口建立 tcp 连接,以和 nginx 进程进行通信。
连接建立后,浏览器发起请求
GET /index.html HTTP/1.1
HOST: test.com- nginx 响应请求,这里客户端请求的是静态文件,直接返回即可;对于动态内容的请求,见下一小节
Content-type: text/html
Date: Mon, 26 Apr 2010 20:23:51 GMT
Server: nginx/0.6.35
1e24
Connection closed by foreign host.
此响应包含 http header 和 html文本 两大部分。
浏览器解析响应。对于 html 响应中包含的元素,需要进行新的一次请求,如上例中的 js 文件;若浏览器和服务器软件协商打开 keepalive 模式,则此次新的请求可以在已有的 tcp 连接上进行,否则需要重新三次握手来建立新连接。
2. 动态内容处理
往往我们看到的网页都是用各种语言动态生成的,如 PHP 语言和使用 python 语言的 django 框架。
- 用户输入 http://www.test.com/ 这样的 url,请求网站的根目录。
- 对于 php,配置服务器,指定默认的响应文件,如 index.php,并且配置以何种方式处理以 .php 结尾的文件。
location / {
index index.php;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 我们以这种方式来处理 php 文件,某程序监听了本机的9000端口。
}
}
location 后面跟的是相对目录,即 url 中 host 后面的目录部分。 对于 django 这种提供较完善解决方案的框架,它靠匹配 url 来进行决策,我们就不指定默认文件了,把所有请求全部交给某程序处理,配置如下。
location / {
fastcgi_pass 127.0.0.1:8000;
}
我们还可以控制让静态文件直接由 nginx 返回而不让 django 处理。
location /static/ {
alias /var/www/djangoproject/static/;
}
2.1 CGI & FASTCGI
apache、lighttpd 等 web server 软件都支持传统的 CGI,在简单配置后,将如下脚本(hello.py)放入指定目录。
print "Content-type: text/html"
print ""
print ""
print "Hello World"
print ""
然后访问 http://test.com/cgi-path/hello.py 就能看到相应内容了。
其处理的过程大概是这样:对于每一个请求,创建一个新进程,然后初始化并执行上述程序,最后将数据返回给 web server 并释放内存资源。
后来出现的 fastcgi 方式对传统方法进行了改进,首先启动一个或多个 fastcgi 进程(可理解为 fastcgi 服务器/网关),然后对于每一个浏览器请求,web server 去连接已经启动好的 fastcgi 进程并转发请求,待得到结果后关闭此连接。
当然 fastcgi 方式和协议需要服务器软件支持,上述 3 种 web server 软件都支持,有关 fastcgi 好处和性能的讨论这里不再介绍,网上一抓一大把。
2.2 django
对于 django,概念有些拗口,注意区分 fastcgi 方式和协议的区别。
- WSGI,Web Server Gateway Interface,是 Python 应用程序和 Web 服务器之间的一种接口,能以 fastcgi 作为两者通信的底层协议规范
- django 能以 fastcgi 方式(而不是协议)启动自带的服务器进程,此进程叫做 WSGIServer,该 server 由 python 的 flup 库提供,具体采用什么协议可以在 manage.py runfcgi 的 protocol 参数中指定,注意除了fastcgi 协议(参数中写为 fcgi)还能选择 scgi 等其他协议。
- 现在我们知道 WSGIServer 就是上面介绍的 fastcgi 服务器/网关,它监听一个 tcp 端口(还能以 unix socket 方式监听,这里不再介绍),也就是前面配置文件中的 8000 端口。
- 在启动 WSGIServer 的时候需要指定一个 WSGIHandler,这个 Handler 关联了请求(request)和我们写的 django 应用,在每次请求到来时 Handler 会加载应用的 settings、middleware 和 环境变量,然后请求经 url 解析并交给指定 views 处理,最终处理结果返回给 WSGIServer。
一些参考:
- django/core/servers/fastcgi.py
- django/core/handlers/wsgi.py
- http://blogs.sun.com/oswald/entry/good_idea_python_with_fastcgi CGI 和 FASTCGI 的区别
- http://osdcpapers.cgpublisher.com/product/pub.84/prod.21 WSGI 入门的 PDF
- http://www.douban.com/note/13508388/ WSGI、flup、fastcgi、web.py的关系