为什么Nodejs会比其他语言的Hello world性能要好?
从String到Buffer, 从Buffer到Stream,文件数据流,网络数据流
Javascript可以轻松地通过Socket实现各种网络协议,还有功能完善的HTTP模块。
Nodejs能带来更多什么魔法呢?
第三方模块的持续增长和完善,让Nodejs的世界变得越来越有趣。
模块管理神器:npm
from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, \
Application
class MainHandler(RequestHandler):
def get(self):
self.write("Hello, world")
application = Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8080)
IOLoop.instance().start()
package main
import (
"http"
"io"
)
func handler(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello, world")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
private void handleHttpRequest(
ChannelHandlerContext ctx,
HttpRequest req) throws Exception {
HttpResponse res =
new DefaultHttpResponse(HTTP_1_1, OK);
res.setHeader(CONTENT_TYPE,
"text/html; charset=UTF-8");
setContentLength(res, 11);
res.setContent(
ChannelBuffers.copiedBuffer(
"hello world",
CharsetUtil.US_ASCII));
sendHttpResponse(ctx, req, res);
}
var http = require('http');
http.createServer(function(req, res){
res.end('Hello, World');
}).listen(8080);
var cluster = require('cluster')
, http = require('http');
var server =
http.createServer(function(req, res) {
res.end('Hello World');
});
cluster(server)
.set('workers', 4)
.use(cluster.stats())
.listen(8080);
$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
$ cat /etc/issue | grep Linux
$ ab -c 30 -n 1000000 http://127.0.0.1:8080/
Name | 30 threads rps | 100 rps | 1000 rps | 5000 rps |
---|---|---|---|---|
Nodejs | 7,287 | 7,038 | 6,786 | 6,912 |
Tornado | 2,967 | 2,966 | 2,967 | 2,982 |
Go | 5,214 | 5,157 | 5,080 | 5,164 |
Netty | 13,526 | 13,351 | 11,332 | 7,921 |
Nodejs 4P | 14,826 | 14,332 | 12,161 | 8,287 |
解决:流数据处理问题
解决:V8 1GB 堆栈内存限制
// buffer.js
var a = new Buffer(10);
console.log(a, a.toString());
var b = new Buffer('QCon2011杭州');
console.log(b, b.toString());
$ node buffer.js
<Buffer 05 08 4e 00 2f 0f 26 05 04 4e> '\u0005\bN\u0000/\u000f&\u0005\u0004N'
<Buffer 51 43 6f 6e 32 30 31 31 e6 9d ad e5 b7 9e> 'QCon2011杭州'
文件的I/O是由标准POSIX函数封装而成。
所有的方法都提供了异步和同步两种方式。
提供了一种异步网络包装器,
它包含创建服务器和客户端(称为streams)所需的方法(只提供异步方式)。
Node中的HTTP接口在设计时就考虑到了要支持HTTP协议的很多特性,并且使用简单。
特别是可以处理那些内容庞大,有可能是块编码的消息。
该接口被设计为从不缓冲整个请求或相应,这样用户就可以以流的方式处理数据。
var fs = require('fs');
// $ touch /tmp/helloSync
fs.renameSync('/tmp/helloSync', '/tmp/worldSync');
var stats =
fs.statSync('/tmp/worldSync');
console.log('statsSync:'
+ JSON.stringify(stats));
var fs = require('fs');
// $ touch /tmp/hello
fs.rename('/tmp/hello', '/tmp/world', function (err) {
if (err) throw err;
fs.stat('/tmp/world',
function (err, stats) {
if (err) throw err;
console.log('stats: '
+ JSON.stringify(stats));
});
});
// chat.js
var net = require('net');
var clients = [];
net.createServer(function(client) {
client.write('Enter your name:\n');
client.once('data', function(data) {
var username = data.toString().trim();
clients.push(client);
broacast(username + ' : Join!\n');
client.on('data', function(data) {
var text = username + ' : ' + data;
broacast(text);
});
});
}).listen(11021);
// 单进程的优势。。。
function broacast(text) {
console.log(text.trim());
var i = 0, l = clients.length;
for(; i < l; i++) {
var c = clients[i];
c.write(text);
}
};
mk2 : Join!
mk2 : Hello qcon2011 hangzhou!
Enter your name:
mk2
mk2 : Join!
Hello qcon2011 hangzhou!
mk2 : Hello qcon2011 hangzhou!
var http = require('http');
http.createServer(function(req, res) {
if(req.url === '/') {
res.end('Hello world');
} else {
res.end('HTTP ' + req.method
+ ' : ' + req.url);
}
}).listen(8080);
var http = require('http');
var options = {
host: 'www.google.com',
port: 80,
path: '/'
};
http.get(options, function(res) {
console.log("Got response: "
+ res.statusCode);
res.on('data', function(data) {
console.log(data.toString());
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
例如请求HTTP服务器的request是一个流,类似于stdout(标准输出)。
读取文件可以是一个文件流。
var readstream =
fs.createReadStream(uploadfile);
readstream.on('data', function(chunk) {
console.log('write', chunk.length);
// 向服务器发送数据
req.write(chunk);
});
readstream.on('end', function() {
req.end();
});
嫌既监听data又要监听end事件很麻烦?那就试试pipe吧,简直像安装水管那么简单。
readstream.pipe(req);
通过readStream读取大文件并发送到网络中去:upload_file.js
var writestream =
fs.createWriteStream(savefile);
res.pipe(writestream);
writestream.on('close', function() {
callback(null, res);
});
通过WriteStream接收网络中得到的数据:download_file.js
Nodejs能带来更多什么魔法呢?
/
#