一直在思考 Nodejs 除了高效的异步IO
还有哪些东西是值得花更多多时间去理解的呢?
进程通讯,内存管理,异步流程控制,[Stream],node 模块
以下是废话可以略过
个人认为Nodejs是应对io密集,高并发,高性能需求应用的最佳选择之一。
Nodejs 使用 libuv (在windows平台使用IOCP, 在FreeBSD上使用`kqueue`,在*nux上使用[e]poll)。使得Nodejs在各种平台上具有相同的性能, 这点与python的Tornado,nginx不同。
Nodejs 两大特点
Feature -- 使用了 unix:socket 进程通讯模型
。可以使用unix程序的实际思路,将大的程序产分成小的模块,最终使用进程间通讯的机制将小的模块程序连接在一起,形成统一的服务。可以轻松实现高可用高性能的集群。
Feature -- Stream 具有异步的特性
。我么可以将一个文件或一段内容分为未知个制定大小的 chunk 去读取,每读取到一个 chunk 我们就将他输出。直到文件读完。这就像 http1.1 种支持的 Transfer-Encoding: chunked
那样。 (chunk可以以任何的形式存在,Nodejs 默认是以Buffer的形式存在,这样更高效
)。Nodejs 中的Stream具备Unix系统上的一个超级特性就是 (pipe -- 管道
)
说起 Nodejs 中的 流不得不谈起 *nix 系统.(可能是应为 nodejs 的设计者大量借鉴了性能出色的unix底层设计)
unix 下使用管道的可以高效的帮我们完成工作
$ ~ -> cat /etc/passwd | grep admin # 查看系统中用户的详细信息
$ ~ -> ps aux | grep sshd #查看 sshd 进程基本运行状况
这样一条命令执行后 你的电脑就可以通过ssh证书形式登陆远程终端。
$ ~ -> ssh [email protected] 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub
这就是一个 将本地的 id_rsa.pub
文件以流的形式 发送给 远程主机(8.8.8.8
)的cat程序,并以用户 yin
的身份将 流写入到 /homeyin/.ssh/authorized_keys
文件中。这个过程是非常高效的。
同样 nodejs 的 strame 也是这样工作的。 |
管道符在node中是使用 pipe()
来提供的。 'small-program design and unix philosophy' 这与node的设计非常契合。
好的让我们从现在开始探讨nodejs中的stream吧。
还记得 第一个 nodejs hello,world http server吗?
var http = require('http');
var server = http.createServer(function(req, res){
res.writeHeader(200, {'Content-Type': 'text/plain'});
res.end('hello, world');
});
server.listen(8080);
console.log('http server running on port 8080 ...');
后来我们有学习到了,fs 中的 readFile
方法,终于可以讲一个文件以超文本或超媒体的像是发送到浏览器了。
于是 ...
#server.js
...
fs.readFile(__dirname + '/data.html', 'utf-8', function(err, data){
if(err) {
res.writeHeader(500, {'Context-Type': 'text/plain'});
res.end('specify file not exists! or server error!');
}
else{
res.writeHeader(500, {'Context-Type': 'text/html'});
res.end(data);
}
})
...
#data.html
my first static file server!
现在我们需要思考一下,如果 我们要发送的不是一个单纯的文本文件而是超媒体文件比如说 Google 2014 IO 大会
的全程高清视频文件 .mp4
格式。长度2个多小时1080p。大概4个多GB。
已知 readFile
的工作方式是将文件读取到内存。那么这么大一个文件显然是不能这么做的。那该怎么办呢?是之后就需要使用 strame 的来做。那么是这样的。
...
fs.createReadStream(__dirname + '/vedio.mp4').pipe(res)
...
代码很短,没有回调,是的。
我们查看 response 的 header 的话。 node server 会自动帮我们加上这样的标头.
Connection: Keep-Alive
Transfer-Encoding: chunked
我们是使用 持久连接 以 chunk
的形式 将我们的视频文件发送到我们的客户端。这是一个直观的形式。
接着看,请移步 GitHub。如果你想深入许学习 nodejs 这篇文章你不能错过