人们都说, 阅读源码是提高编程水平的一个极好的方法, 但是如何找到一个适合自己阅读的源码, 就蛋疼的很。 优秀的开源项目非常多, 肯定是看不完的。 而且如果没有一个明确的目的, 只是因为火就看, 则事倍功半。
我更像一个后台开发程序员, 所以以下观点都基于后台程序员的视角出发。

从 Node.js 和 Tornado 出发
在几个月前, 我学习了 Tornado 框架并用来做了一个项目; 而 Node.js 则是最近几天才开始学的。 所以很可能会有说的不严谨的地方。
Tornado 是一个异步非阻塞服务器应用与轻量级Web框架的结合体。 Node.js 则是一个开源跨平台的运行环境(runtime
environment)。 在我看来, Node.js 基本上就是一个服务器应用了, 因为这一部分和 Tornado
的服务器部分几乎是一模一样。
我们的问题主要是应该选择什么样的开源代码来阅读, 目前为止, 我们可以选择的项目有Tornado和Node.js了。 先不着急做出决定,
继续向深处探索一番。 首先化简问题, 因为 Node.js 的优势并非仅仅是异步非阻塞提供的高性能, 还有很多其他的东西,
我们暂时不管那些其他的部分。
如果学习过操作系统, 就会知道 Linux 下这两个程序之所以达到如此高性能的效果, 归功于 Linux 2。6 Kernel
提供的epoll。 我的思路是, Node.js 如果在 Linux 下运行, 一定会调用操作系统提供的 epoll; 如果在 Windows
下运行, 一定会调用操作系统提供的 IOCP。
顺着这个思路, 我发现了 libuv 和 pyuv 这两个开源项目。
屡清关系
上面提到了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