天天看點

如何選擇一個适合自己的開源項目來閱讀

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

我更像一個背景開發程式員, 是以以下觀點都基于背景程式員的視角出發。

如何選擇一個适合自己的開源項目來閱讀

從 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 如何傳回給使用者的細節的。

如何選擇一個适合自己的開源項目來閱讀

圖檔: web架構與伺服器的關系

由于同時會有很多用戶端向伺服器發起請求, 伺服器要盡快處理這些請求, 提高性能一般是讓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 的一些模糊的認識, 逐漸梳理出從使用者發起請求,

到作業系統甚至硬體層面的一條比較清晰的路線。 雖然一行源碼都還沒看, 已經知道了我們看不同的源碼, 分别能學到什麼知識。 在這個基礎上,

選擇适合自己目前需求的源碼來閱讀, 就能事半功倍了。

作者:jecvay

來源:51cto