從零開始搭建論壇(一):Web服務器與Web框架

以前用 Django 作過一個小的站點,感受Django太過笨重,因而就準備換一個比較輕量級的 Web 框架來玩玩。Web.py 做者已經掛掉,項目很久沒有更新,因此不許備用它。而 Flask 也是一個成熟的輕量級 Web 框架,在 github 上有衆多的 Star 和 Fork,文檔和擴展也很豐富,值得學習。html

學習一個框架最好的方式就是用框架作一個項目,在實戰中理解掌握框架。這裏我用 Flask 框架,使用 Mysql 數據庫作了一個論壇系統。麻雀雖小,五臟俱全,論壇效果圖以下:python

論壇系統截圖

下面是論壇的基本功能:ios

  • 完整的用戶模塊(註冊、登陸,更改、找回密碼、信息修改、站內消息通知);git

  • 豐富的論壇模塊(建立、回覆話題,站內搜索,markdown支持,@user 提醒);github

  • 強大的後臺管理,支持屏蔽用戶、話題、評論,支持各類條件搜索話題、評論;web

本博客將會用一系列文章,記錄論壇系統搭建的過程,但願對剛入門Web開發的同窗有所幫助。sql

咱們常常據說 Django, Flask 這些 python 語言的Web 框架,那麼框架究竟是什麼,Web框架和Web服務器(Nginx, Apache等)有什麼區別?離開框架還能用 Python 搭建Web站點嗎?要解決這些疑問,咱們有必要來理解下 Web 服務器的工做原理,以及 Web 框架的本質。數據庫

Web 服務器

當咱們在瀏覽器輸入URL後,瀏覽器會先請求DNS服務器,得到請求站點的 IP 地址。而後發送一個HTTP Request(請求)給擁有該 IP 的主機,接着就會接收到服務器給咱們的 HTTP Response(響應),瀏覽器通過渲染後,以一種較好的效果呈現給咱們。這個過程當中,正是Web服務器在幕後默默作貢獻。django

簡單來講,Web服務器是在運行在物理服務器上的一個程序,它永久地等待客戶端(主要是瀏覽器,好比Chrome,Firefox等)發送請求。當收到請求以後,它會生成相應的響應並將其返回至客戶端。Web服務器經過HTTP協議與客戶端通訊,所以也被稱爲HTTP服務器。編程

Web 服務器

Web服務器的工做原理並不複雜,通常可分紅以下4個步驟:創建鏈接、請求過程、應答過程以及關閉鏈接

  1. 創建鏈接:客戶機經過TCP/IP協議創建到服務器的TCP鏈接。

  2. 請求過程:客戶端向服務器發送HTTP協議請求包,請求服務器裏的資源文檔。

  3. 應答過程:服務器向客戶機發送HTTP協議應答包,若是請求的資源包含有動態語言的內容,那麼服務器會調用動態語言的解釋引擎負責處理「動態內容」,並將處理獲得的數據返回給客戶端。由客戶端解釋HTML文檔,在客戶端屏幕上渲染圖形結果。

  4. 關閉鏈接:客戶機與服務器斷開。

下面咱們實現一個簡單的 Web 服務器。運行示例程序後,會監聽本地端口 8000,在瀏覽器訪問 http://localhost:8000 就能看到響應內容。而咱們的程序也可以打印出客戶端發來的請求內容,以下圖:

簡單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應用程序

以 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 架構,以下圖所示:

MVC 架構

用戶輸入 URL,客戶端發送請求,控制器(Controller)首先會拿到請求,而後用模型(Models)從數據庫取出全部須要的數據,進行必要的處理,將處理後的結果發送給 視圖(View),視圖利用獲取到的數據,進行渲染生成 Html Response返回給客戶端。

以 python web 框架 flask 爲例,框架自己並不限定咱們用哪一種架構來組織咱們的應用,不過 flask 能夠很好地支持以 MVC 方式組織應用。

控制器:flask 能夠用裝飾器來添加路由項,以下:

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

模型:主要用來取出須要的數據,以下面函數中操做:

@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 來渲染頁面,下面的模版文件指定了頁面的樣式:

{% 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應用。

WSGI 適配

下一篇咱們將會仔細分析 WSGI 接口標準,而後一塊兒來寫一個簡單的 WSGI Web 服務器。

本文由 selfboot 發表於 我的博客,採用署名-非商業性使用-相同方式共享 3.0 中國大陸許可協議。
非商業轉載請註明做者及出處。商業轉載請聯繫做者本人。
本文標題爲: 從零開始搭建論壇(一):Web服務器與Web框架
本文連接爲: http://selfboot.cn/2016/07/28...

更多閱讀

本身動手開發網絡服務器(一)
本身動手開發網絡服務器(二)
本身動手開發網絡服務器(三)
Web服務器網關接口實現原理分析
Python最佳實踐指南:Web 應用
淺談Python web框架
Python CGI編程
Django vs Flask vs Pyramid: Choosing a Python Web Framework
PEP 333 -- Python Web Server Gateway Interface v1.0
WSGI簡介
Model-View-Controller (MVC) Explained -- With Legos

相關文章
相關標籤/搜索