如何選擇一個適合自己的開源專案來閱讀

發表於2015-09-10

人們都說, 閱讀原始碼是提高程式設計水平的一個極好的方法, 但是如何找到一個適合自己閱讀的原始碼, 就蛋疼的很. 優秀的開源專案非常多, 肯定是看不完的. 而且如果沒有一個明確的目的, 只是因為火就看, 則事倍功半.

我更像一個後臺開發程式設計師, 所以以下觀點都基於後臺程式設計師的視角出發.

從 Node.js 和 Tornado 出發

在幾個月前, 我學習了 Tornado 框架並用來做了一個專案; 而 Node.js 則是最近幾天才開始學的. 所以很可能會有說的不嚴謹的地方.

Tornado 是一個 非同步非阻塞伺服器應用 與輕量級 Web框架 的結合體. Node.js 則是一個開源跨平臺的 執行環境(runtime environment). 在我看來, Node.js 基本上就是一個伺服器應用了, 因為這一部分和 Tornado 的伺服器部分幾乎是一模一樣.

我們的問題主要是應該選擇什麼樣的開原始碼來閱讀, 目前為止, 我們可以選擇的專案有 Tornado 和 Node.js 了. 先不著急做出決定, 繼續向深處探索一番. 首先化簡問題, 因為 Node.js 的優勢並非僅僅是非同步非阻塞提供的高效能, 還有很多其他的東西, 我們暫時不管那些其他的部分.

Tornado = AIO Server + Web Framework
Node.js = AIO Server

如果學習過作業系統, 就會知道 Linux 下這兩個程式之所以達到如此高效能的效果, 歸功於 Linux 2.6 Kernel 提供的epoll . 我的思路是, Node.js 如果在 Linux 下執行, 一定會呼叫作業系統提供的 epoll; 如果在 Windows 下執行, 一定會呼叫作業系統提供的 IOCP .

順著這個思路, 我發現了 libuv 和 pyuv 這兩個開源專案.

libuv : 一般認為, libuv 是因 nodejs 而生. libuv的作用是對使用者隱藏作業系統的差異, 封裝Linux的 libev 和 windows 的 IOCP 等等, 提供跨平臺的非同步操作庫.
pyuv : 給 Python 提供一個呼叫 libuv 的介面

屢清關係

上面提到了nodejs, tornado, libuv, pyuv, libev, IOCP 這些概念(專案), 他們中大部分都可以找到開原始碼, 如果想要從中選擇出合適自己學習的專案, 最好的辦法是先縷清他們的關係.

首先, Tornado 和 node.js 都可以用來做網站後臺伺服器應用. 而 Tornado 更是提供了一個 Web 框架.

Tornado 的 Web 框架提供了檢視和路由功能, 利用這一點我們可以很容易寫出一個 MVC 模式的 Web 應用. 對於Web框架來說, 他直接從伺服器應用拿到使用者的 request, 處理完畢後得到一個 response, 直接給回伺服器就可以了, 是不需要了解 request 如何傳輸過來以及 response 如何返回給使用者的細節的.

由於同時會有很多客戶端向伺服器發起請求, 伺服器要儘快處理這些請求, 提高效能一般是 讓cpu在單位時間裡面儘量可以處理更多的I/O請求 , 方法一般就是採用阻塞的多執行緒, 或者非阻塞的單執行緒(當然也可以多執行緒或者多程式).

無論是採用哪一種I/O模型, 都要有作業系統的支援, 如果CPU沒有中斷功能, 作業系統就沒有鎖的功能, 也就沒有訊號量, 沒有Monitor等一系列同步機制.

對於 Tornado 來說, Python 直譯器提供了上述一系列的同步機制. 因此 Tornado 到底能用什麼樣的 I/O 模型, 直接取決於 Python 直譯器.

而 Python 直譯器是執行在作業系統之上, 如果作業系統不提供鎖, 那麼直譯器也無法做出一把鎖. 因此 Tornado 到底能用什麼樣的 I/O 模型, 間接取決於作業系統.

我想 Node.js 也是一樣的道理.

得出結論

如果想知道一個網站的框架是如何將 路由 , 檢視(html, css, js之類) , 資料處理 拼在一起的, 那麼可以閱讀 Tornado 原始碼中的 Web 框架部分.

如果想知道同時有很多很多的 request 到來, 伺服器應用是如何利用作業系統提供的介面來完成 高併發 處理的, 可以閱讀 Tornado 的伺服器部分或者 Node.js的原始碼

如果想知道, 不同的作業系統提供了不同的介面, 如何在這個基礎上構建出一個 跨平臺的統一介面 , 可以閱讀 libuv 的原始碼

如果想知道在 Linux 作業系統下, 到底是如何 實現這些I/O介面 的, 可以閱讀 libev 的原始碼

如果想知道如何利用 libuv, 在 Python 下也可以呼叫跨平臺 I/O 介面, 可以閱讀 pyuv 的原始碼

不僅如此, 我們由結論還可以知道更多: 如果想看 libuv 的原始碼, 知道 libuv 是如何實現的, 首先得會用它. 只有知道它的作用, 看起原始碼來才有一個目的性. 要想知道如何使用 libuv, 得參考其上面一層的 Tornado 原始碼中的很小一部分, 或者查閱 libuv 的文件.

選擇原始碼的一般方法

  • 列出一些感興趣的關鍵字
  • 對關鍵字的上層和下層進行了解
  • 梳理出整個關係圖
  • 得出結論, 做出選擇

經過剛剛幾個步驟, 我們由對 Tornado 和 Node.js 的一些模糊的認識, 逐漸梳理出從使用者發起請求, 到作業系統甚至硬體層面的一條比較清晰的路線. 雖然一行原始碼都還沒看, 已經知道了我們看不同的原始碼, 分別能學到什麼知識. 在這個基礎上, 選擇適合自己當前需求的原始碼來閱讀, 就能事半功倍了.

相關文章