Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Node.js在淘宝的应用实践

d2forum
July 20, 2012
19k

 Node.js在淘宝的应用实践

各种兼容库,框架的出现和发展,使得前端技术已经不再是前端的瓶颈了。Node.js的出现,可以帮助前端工程师打破了与后端开发之间的壁垒,形成真正的大前端环境。主题将分享Node.js Web开发经验,发现并释放前端工程师已有价值。

d2forum

July 20, 2012
Tweet

Transcript

  1. 关于我 • CNode社区 • 前端 at SAP for Mobile Web

    • 前端 at 淘宝数据产品部 连IE6都能 兼容的男 人 2
  2. 好奇心 & 满足感 • HTTP协议栈:深入后端,反哺前端 • Status code • Cookie

    & Session • Request & Response • Web Framework • 高性能JavaScript平台 • 拓宽视野 8
  3. Go, go, go!!! 9 var http = require('http');http.createServer(function (req, res)

    { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');}).listen(1337, '127.0.0.1');console.log('Server running at http://127.0.0.1:1337/'); % node example.jsServer running at http://127.0.0.1:1337/
  4. $.get("template", function (template) { // something $.get("data", function (data) {

    // something $.get("l10n", function (l10n) { // something render(template, data); }); }); }); 问题:异步协作 • 嵌套还是并行? 13 var proxy = new EventProxy(); proxy.all("template", "data", "l10n", render); $.get("template", function (template) { // something proxy.trigger("template", template); }); $.get("data", function (data) { // something proxy.trigger("data", data); }); $.get("l10n", function (l10n) { // something proxy.trigger("l10n", l10n); });
  5. 问题:异步还是同步 • 复杂的异步编程 var proxy = new EventProxy(); var status

    = "ready"; var _getFile = function (callback) { proxy.once("template", callback); if (status === "ready") { fs.readFile("views/index.html", function (err, file) { status = "pending"; proxy.fire("template", err, file); }); } }; var _template; var getTemplate = function (callback) { if (_template) { callback(null, _template); } else { _getFile(function (err, file) { if (!err && !_template) { _template = file.toString(); } callback(null, _template); }); } }; 同步 + 缓存,妥妥滴 var view = fs.readFileSync("../views/index.html", "utf8"); 14
  6. 问题:缓存的使用 var map = {}; var get = function (key)

    { return map[key]; }; var set = function (key, value) { map[key] = value; }; // 检查缓存 if (!get(key)) { // 从数据库或别的地方获取了对象后,放进缓存中 set(key, value); } var LimitableMap = require('limitablemap'); var map = new LimitableMap(1000); map.set("key1", "key1"); map.get("key1"); 15
  7. 问题:Buffer对象 var data = ""; res.on('data', function (chunk) { //

    chunk是一个Buffer对象 data += chunk;// 隐藏的toString() }) .on("end", function () { //对data转码 }); 17 // 正确的方法 var chunks = []; var size = 0; res.on('data', function (chunk) { chunks.push(chunk); size += chunk.length; }); res.on('end', function () { var data = null; switch(chunks.length) { case 0: data = new Buffer(0); break; case 1: data = chunks[0]; break; default: data = new Buffer(size); for (var i = 0, pos = 0, l = chunks.length; i < l; i++) { var chunk = chunks[i]; chunk.copy(data, pos); pos += chunk.length; } break; } // 简单且正确的方法 var bufferHelper = new BufferHelper(); req.on("data", function (chunk) { bufferHelper.concat(chunk); }) .on('end', function () { var html = bufferHelper.toBuffer().toString(); });
  8. 问题:多核CPU的利 用 • 单线程与多核CPU • 单线程因为异常退出? • 仿若熟悉的Web Worker: child_process

    • 进程与消息 var cluster = require('node-cluster'); var master = new cluster.Master(); master.register(8080, 'app.js'); master.dispatch(); var http = require('http'); var cluster = require('node-cluster'); var worker = new cluster.Worker(); var server = http.createServer(function (req, res) { // server }); worker.ready(function (socket) { server.emit('connection', socket); }); 19 负载均衡 多核利用 提升稳定
  9. 实践:运维 • 异常 • 日志 • 监控 • 部署 •

    备份容灾 21 // 异步方法中try catch是不靠谱滴 // 异步方法的异常 async(function (err, data) { if (err) { logger.error(err); return; // TODO } // TODO }); 进程数量 CPU 内存 Load 磁盘IO 流量 双机房 双Redis MRedis模块 双MongoDB MongoSkin 数据源集群