Node 专题一: 起源

Node的诞生

  • 2009年3月,Ryan Dahl 第一次在博客上宣布准备基于v8创建一个轻量级的web服务器并提供一套库。

    2010年年底,Node.js获得Joyent资助,创始人Ryan Dahl加入Joyent全职负责Node.js,Joyent 是一个提供云计算服务的公司,github上node的源代码的管理就是joyent这个公司,现在github上已经找不到早起ryan上传的node最初版本。

    2012年 ryan将node的版本发布和bug修复任务转交给了Isaac Z Schlueter(npm的作者)。


为什么是javascript

下面为ryan接受采访的一段记录


    BostInno: 你在创建node的时候,是在试图解决什么问题?
  • 我经常需要写一些基于事件的程序,我喜欢设计开发基于事件的服务器,因为我觉得他们很容易理解,状态被保存,有可以不断的修改状态。你可以无限的接收socket请求,我可以只使用非阻塞IO就可以使服务器的延迟非常低。

  • 为什么大多数人不设计一种更简单和有效率的程序,因为他们需要用阻塞的库。基于事件的设计是一种全有或者全无的方式,如果你不阻塞IO的话,你可以仅用一个操作系统线程来处理大量的IO,但是如果你做了,那么了你将锁住你的所有流程。为每个IO使用一个线程也是不错的,他并不是很慢。我想创建一个仅使用非阻塞IO的系统。

  • 同时,我当时正在写大量的小型HTTP服务器。我经常很沮丧,因为我不能从web服务器那里获得原始的请求数据,除非我写一个Apache或者Nginx的模块。而动态分析器可以很容易构造一个服务器。

    BostInno: 为什么你开始要选择Javascript作为node的语言呢?
    
  • Dahl: 开始我没有那么做,我用C、Lua和Haskell做了几个失败的小项目。Haskell很不错,但是不还没有足够聪明可以去玩通GHC(Haskell的编译器)。Lua是一种不太理想,但是很可爱的语言,我并不喜欢他,因为他已经有了大量的包含阻塞代码的库了。无论我做了什么,有些人总是愿意去读取有阻塞的Lua库。C语言有一些和Lua相似的问题,而且它的开发门槛有些高。我开始的确想写一种像node.js的libc,我也的确做了一段时间。这个时候V8也出来了,我也做了一些研究,我突然意识到,Javascript的确是一种完美的语言,他有我想要的一切:单线程,没有服务端的IO处理,没有各种历史存在的库。

    BostInno: 接下来3个月、6个月或者12个月node将如何发展?
    
  • Dahl: Node是一个强制不共享服务器的任何资源的单线程、单进程系统。他的确有一些好的网络库,我相信这是一个设计很大型的分布式系统的很好的基础。而这些节点需要被组织,通过一个通信协议,互相通知对方如何连接。接下来几个月,我将致力于写一些能够支持这种网络的库,以使分布式网络程序开发更加容易。

  • 在今年2月,我们将发布第二个稳定版本:V0.4。这个版本将大大提升内存利用率,和一个新的SSL/TLS系统,一个内建的调试器,更快的定时器,删掉了一些缺陷,以及一个新的V8的版本。 有希望在接下来6个月之内,我们将试图发布一个Node 1.0的正式版本。 我的一个想法是限制核心程序的大小,不让他变的太大,我们我们不会无休止的增加一些特性。 V1.0将看上去很像现在的Node, 目前我们仍然有大量的bug需要修复。

    BostInno: 还有任何你希望做的东西吗?
    
  • Dahl: 是的,许多事情。 例如,我希望我没有用过CommonJS模块系统,它实在太复杂,并且和浏览器的工作方式很不同。 我希望我没有用过WAF构建系统,他可以工作,也不错,但是他做了比需要更多的事情。我也许可以从WAF中挖掘挖掘一些东西出来。


node的特点

  • 异步I/O

    我们首先要理解一些关键字的意思:

    1.异步与同步的区别
    
  • 异步就是你可以边吃饭边喝水,同步就是你必须在吃完饭才可以喝水。如果你想从数据库拉取大量数据就需要等待一些时间,那么同步的编程模式会等待数据读取完成后再去做其它任务。如果是异步的编程模式,则程序在等待数据返回的同时可以去执行其他任务。这里的I/O(input , output)接口的功能是负责实现CPU通过系统总线把I/O电路和外围设备联系在一起。

    2.阻塞与非阻塞的区别
    
  • 阻塞( blocking )、非阻塞( non-blocking ):可以简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待那就阻塞了(进程或线程就阻塞在那了,不能做其它事情),否则就可以理解为非阻塞(在等待的过程中可
    以做其它事情)

    同步 I/O 操作:实际的I/O操作将导致请求进程阻塞,直到 I/O 操作完成
    异步 I/O 操作:实际的I/O操作不导致请求进程阻塞。
    阻塞式I/O,非阻塞式I/O,I/O复用,信号驱动I/O模型都属于同步I/O


  • 异步I/O的实现

    1.异步I/O与轮询技术
    
  • 当进行非阻塞I/O调用时,要读到完整的数据,应用程序需要进行多次轮询,才能确保读取数据完成,以进行下一步的操作。轮询技术的缺点在于应用程序要主动调用,会造成占用较多CPU时间片,性能较为低下。现存的轮询技术有以下这些:

    • read
    • select
    • poll
    • epoll
    • pselect
    • kqueue
  • read是性能最低的一种,它通过重复调用来检查I/O的状态来完成完整数据读取。select是一种改进方案,通过对文件描述符上的事件状态来进行判断。操作系统还提供了poll、epoll等多路复用技术来提高性能。轮询技术满足了异步I/O确保获取完整数据的保证。但是对于应用程序而言,它仍然只能算是一种同步,因为应用程序仍然需要主动去判断I/O的状态,依旧花费了很多CPU时间来等待。

    2.理想的异步I/O模型
    
  • 理想的异步I/O应该是应用程序发起异步调用,而不需要进行轮询,进而处理下一个任务,只需在I/O完成后通过信号或是回调将数据传递给应用程序即可。

  • 幸运的是,在Linux下存在一种这种方式,它原生提供了一种异步非阻塞I/O方式(AIO)即是通过信号或回调来传递数据的。不幸的是,只有Linux下有这么一种支持,而且还有缺陷(AIO仅支持内核I/O中的O_DIRECT方式读取,导致无法利用系统缓存。以上都是基于非阻塞I/O进行的设定。另一种理想的异步I/O是采用阻塞I/O,但加入多线程,将I/O操作分到多个线程上,利用线程之间的通信来模拟异步。Glibc的AIO便是这样的典型。然而遗憾在于,它存在一些难以忍受的缺陷和bug。可以简单的概述为:Linux平台下没有完美的异步I/O支持。

  • 所幸的是,libev的作者Marc Alexander Lehmann重新实现了一个异步I/O的库:libeio。libeio实质依然是采用线程池与阻塞I/O模拟出来的异步I/O。那么在Windows平台下的状况如何呢?而实际上,Windows有一种独有的内核异步IO方案:IOCP。IOCP的思路是真正的异步I/O方案,调用异步方法,然后等待I/O完成通知。IOCP内部依旧是通过线程实现,不同在于这些线程由系统内核接手管理。IOCP的异步模型与Node.js的异步调用模型已经十分近似。以上两种方案则正是Node.js选择的异步I/O方案。由于Windows平台和*nix平台的差异,Node.js提供了libuv来作为抽象封装层,使得所有平台兼容性的判断都由这一层次来完成,保证上层的Node.js与下层的libeio/libev及IOCP之间各自独立。Node.js在编译期间会判断平台条件,选择性编译unix目录或是win目录下的源文件到目标程序中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值