Tornado-6.0.3源碼分析之前述

閒言之語

許久沒有想起寫博客了,之前嘗試寫了幾遍,但是都沒有好好堅持下來。以致於,很多自己遇到的問題,自己想到的解決方案沒有被記錄下來。如今回想起來,竟也是幾乎全忘光了,突然感覺這種狀態不能這麼繼續下去。如今,在學習python的一個web框架庫tornado,感覺自己應該需要不斷整理輸出自己的思路,記錄自己的學習歷程;對自己而言,也是一種學習方式,對他人而言,也是一種交流方式;本人使用的是tornado-6.0.3版本,屬於比較新的版本。另外,本人是python菜鳥一枚,如果有大神路過,還望能指點一二,不勝感激。

一、相關知識點儲備

要想理解學習Tornado的源碼,至少需要學習瞭解python中類相關的操作,如類繼承、類重載實現、元類等;還需要學習熟悉asyncio庫的基本知識,比如event loop、future相關的知識點,這個是理解tornado底層網絡異步實現的基礎,因爲Tornado 6.0.3版本使用的底層異步網絡就是對asyncio庫的一種重裝包裝;早期版本的tornado底層的異步網絡是自己實現的,主要使用是epoll知識,這部分就不再多說了,想了解早期版本的話,可以網上搜索一下。這裏還是以較新版本爲例。

二、tornado整體框架簡述

Tornado是一個python語言的web框架實現和異步網絡通訊庫。使用非阻塞式網絡IO實現,可以同時支持成千上萬的網絡連接,適合於網絡長連接,websocket通訊和其它需要長連接的應用。其官網文檔說明鏈接是:https://www.tornadoweb.org/en/stable/
正常來說,Tornado庫的相關模塊功能可以劃分爲六大部分。
其一,web服務框架;主要是用於搭建實現web服務相關的功能;
其二,HTTP協議的客戶端和服務端的實現,即完整的支持http協議功能;
其三,異步網絡通訊實現,即實現非阻塞的網絡傳輸;
其四,協程的相關實現庫。
其五,其它服務實現的融合。如WSGI(Web Server Gateway Interface)的支持
其六,整個庫其它公共的實現,如日誌記錄等

既然是要學習源碼,那麼下載一份源代碼是必須的。
Tornado的源碼文件如下所示:
在這裏插入圖片描述
對應於上述的分類,各模塊的劃分如下:

web框架相關
  • web.py 主要是包括了對請求處理類RequestHandler和應用路由查找類Application的定義
  • template.py 包含的是提供靈活的對外輸出的模版實現
  • routing.py 是對路由查找的基本定義實現,上述的Application類就是對這裏定義的相關路由類的繼承與實現
  • escape.py 是對網絡字符轉碼相關的實現
  • locale.py 是web頁面進行國際化翻譯的實現
  • websocket.py 是對於websocket通訊的支持
HTTP 客戶端和服務端相關
  • httpserver.py 非阻塞式 HTTP 服務端的實現定義,這裏是對服務端的邏輯實現定義。
  • httpclient.py 異步HTTP 客戶端的實現定義,這裏是對客戶端的邏輯實現的基本定義,相當於接口定義。真正的相關實現是 simple_httpclient.py 模塊和 curl_httpclient.py 模塊。 其中simple_httpclient是Tornado默認使用的客戶端實現,比較通用簡單些,而curl_httpclient客戶端是依賴於curl庫,提供了一些simple_httpclient沒有的特性功能
  • httputil.py 是包含一些HTTP相關的公共操作,比如HTTP 頭域定義等
  • http1connection.py 是對HTTP 1.x協議的定義實現。
異步網絡定義
  • ioloop.py 是對asyncio庫的包裝定義
  • iostream.py 是對socket連接的包裝。
  • netutil.py 網絡相關的公共操作實現
  • tcpclient.py 基於IOStream的tcp 客戶端實現
  • tcpserver.py 基於IOStream的tcp 服務端實現
其它服務的融合
  • auth.py 鑑權相關
  • wsgi.py 與其它python web框架的對接實現
  • platform.caresresolver.py DNS解析相關的實現
  • platform.twisted.py 實現tornado與Twisted的橋接
  • platform.asyncio.py 實現tornado與asyncio的橋接
其它公共操作
  • autoreload.py 自動重載程序
  • concurrent.py 對asnyncio 的Future的處理操作
  • log.py 日誌記錄
  • options.py 命令行解析實現
  • testing.py unittest測試
  • util.py 普通的公共操作

在代碼實現層面上,其框架設計類圖如下所示。雖然不是每個相關類都體現出來了。但是整體來說,是沒有太大差別的。(PS:後面再回來補充相關的整體類圖說明)
此圖來源自:http://www.nowamagic.net/academy/detail/13321014
在這裏插入圖片描述
可以看到,這是一個向上的層級服務實現。最底下的io event事件進行網絡數據的讀寫,通過再次包裝成IOStream類後,爲TCP傳輸層服務,而Http協議建立在tcp之上,最上面的用戶層是web應用層,涉及到web搭建的各個方面。

三、簡單的例子

在學習介紹Tornado相關的例子前,先來看一下,一個普通的網絡服務器的框架樣子。

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setblocking(0)
sock.bind("", 8888)
sock.listen(128)

while True:
	try:
		connection, address = sock.accept()
		connection.sendall("hello world")
		connection.close()
	except BlockingIOError:
		return

這是一個典型的阻塞式的tcp服務端。所需要完成的步驟是:
1 創建一個socket實例,sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
2 設置該sock實例的參數,如端口可複用等,sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
3 綁定特定的本地端口和地址,sock.bind("", 8888)
4 設置最大監聽緩衝長度,sock.listen(128)
5 等待客戶端的連接,connection, address = sock.accept()
6 與該客戶端進行數據交互處理,在這裏只是由服務端發送了一個"hello world", connection.sendall(“hello world”)
7 處理結束,關閉該客戶端,繼續等待下一個客戶端。connection.close()

這些步驟就是一個處理TCP連接的主要操作。而這個服務器的實現缺陷也是很明顯的。比如,程序只能阻塞等待,而不能做其它事情,這就造成了資源浪費;對於數據的處理過程也是不具備可擴展性,如果要添加其它處理過程,就是修改到原來的代碼等等;那麼Tornado庫,在網絡處理方面就是優化實現了這些,把阻塞的等待變成了異步的網絡監聽,在監聽到有新的連接時,再“激活處理”;下面先簡單看下Tornado提供的簡單例子。

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
	def get(self):
		self.write("hello, World")

if __name__ == "__main__":
	application = tornado.web.Application([
		(r"/", MainHandler),
	])
	application.listen(8888)
	tornado.ioloop.IOLoop.current().start()

在這個例子中,可以看到,主要完成的事情有:
1 實現一個數據處理相關的類,MainHandler,該類繼承自tornado.web.RequestHandler類,並重載實現了get方法。tornado.web.RequestHandler這個類是Tornado提供出來的Web請求的處理基類,其子類只需要關注相應的方法重載即可實現對數據的操作。
2 實例化一個web應用路由application,該application的作用就是當有客戶端,比如瀏覽器訪問 http://127.0.0.1:8888 這個網址時,把該請求提交給MainHandler類的實例處理,類的實例化由application內部實現。
3 設置監聽的端口地址。需要注意的是,這裏的listen方法,不同於上面的例子中的sock.listen,在這個listen方法中,涉及到了上述的創建一個sock實例、設置sock相關參數、綁定相應的端口、設置監聽長度、準備啓動異步網絡監聽,等待客戶端連接;這些所有操作。
4 啓動io 事件循環tornado.ioloop.IOLoop.current().start()。這裏啓動後,步驟3中的異步監聽實現才真正的運行起來。

從這個例子我們可以看到,在功能實現和操作方面,Tornado整體實現上就是簡化了網絡連接相關的操作,提供了方面的可拓展的web應用程序,而於如何創建網絡連接、如何接收客戶端數據、數據是如何提交出來給用戶處理的等等,這些細節,對於庫的使用者,是不必關心的。但是對於源碼查看分析,這些纔是關鍵。

四、總結

這篇裏面,主要是初步接觸Tornado庫,基本瞭解一下Tornado。

  • Tornado 本身概要,它是一個web框架和異步網絡庫實現,適合長連接的應用場景。
  • Tornado 整體的基本分層情況
  • Tornado 簡單使用例子,對比於典型的服務端程序的差別。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章