Successfully reported this slideshow.

D2_node在淘宝的应用实践_pdf版

6

Share

Loading in …3
×
1 of 27
1 of 27

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

D2_node在淘宝的应用实践_pdf版

  1. 1. Node在淘宝的应用实践 这些年,我们⼀一起开发过的Node.js By @朴灵 1
  2. 2. 关于我 连IE6都能兼 • CNode社区 容的男人 • 前端 at SAP for Mobile Web • 前端 at 淘宝数据产品部 2
  3. 3. 议程 • 我为什么要做Node开发 • 准备工作与作品 • Node.js带来的新问题与如何逆袭 • 异步编程 • 缓存与内存 • Buffer • Node.js在淘宝产品中的⼀一点实践 3
  4. 4. 长达半天的欢乐 icons powered by morcha design 前端屌丝的坎坷路 4
  5. 5. Node与前端的亲缘 5
  6. 6. Node与前端的亲缘 6
  7. 7. 左手HTML5右手Node.js • 熟知的JavaScript执行原理/事件循环 • 熟悉的API、事件、单线程、回调 • Ajax/异步 • 相比HTML5,Node将开启更多的可能性 7
  8. 8. 好奇心 & 满足感 • HTTP协议栈:深入后端,反哺前端 • Status code • Cookie & Session • Request & Response • Web Framework • 高性能JavaScript平台 • 拓宽视野 8
  9. 9. Go, go, go!!! var http example.js % node = require('http'); Server running at http://127.0.0.1:1337/ http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); }).listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/'); 9
  10. 10. 作品 10
  11. 11. 全JavaScript堆栈的产品 Connect WebGhost ITier Redis & MRedis MongoSkin Should 11
  12. 12. 前端工程师到Web工程师 让女神青睐 如何摆脱前端屌丝的身份 结果重了10斤 12
  13. 13. 问题:异步协作 var proxy = new EventProxy(); • proxy.all("template", "data", "l10n", render); 嵌套还是并行? $.get("template", function (template) { // something $.get("template", function (template) { proxy.trigger("template", template); }); // something $.get("data", function (data) { { $.get("data", function (data) // something // something $.get("l10n", function (l10n) { proxy.trigger("data", data); }); // something render(template, data); $.get("l10n", function (l10n) { }); // something }); proxy.trigger("l10n", l10n); }); }); 13
  14. 14. 问题:异步还是同步 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 view = fs.readFileSync("../views/index.html", "utf8"); 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); }); } }; 14
  15. 15. 问题:缓存的使用 var map = {}; var get = function (key) { var LimitableMap = require('limitablemap'); return map[key]; }; map = new LimitableMap(1000); var map.set("key1", "key1"); var set = function (key, value) { map.get("key1"); map[key] = value; }; // 检查缓存 if (!get(key)) { // 从数据库或别的地方获取了对象后,放进缓存中 set(key, value); } 15
  16. 16. 问题:Session • V8内存堆栈限制 • 分布式中,Session需要共享(Redis) • 重启应用不丢失session • 多点Redis,备份容灾 16
  17. 17. // 正确的方法 var chunks = []; var size = 0; 问题:Buffer对象 res.on('data', function (chunk) { chunks.push(chunk); size += chunk.length; }); var data = ""; res.on('end', function () { res.on('data', function (chunk) { var data = null; //switch(chunks.length) { // chunk是⼀一个Buffer对象 简单且正确的方法 data 0: data = new =隐藏的toString() case += chunk;//Buffer(0); var break; bufferHelper new BufferHelper(); }) case 1: data = function req.on("data",chunks[0]; (chunk) { .on("end", function () { bufferHelper.concat(chunk); break; })//对data转码 default: .on('end',new Buffer(size); }); data = function () { for (var i = 0, pos = 0, l = chunks.length; i < l; i++) { varvar chunk bufferHelper.toBuffer().toString(); html = = chunks[i]; }); chunk.copy(data, pos); pos += chunk.length; } break; } }); 17
  18. 18. 问题:String传输的性能 • 7k大小的静态文件,需做替换 • String ➛ Buffer • 缓存Buffer,4倍性能提升 18
  19. 19. 问题:多核CPU的利用 var cluster = require('node-cluster'); • 单线程与多核CPU var master = new cluster.Master(); master.register(8080, 'app.js'); master.dispatch(); 负载均衡 • 单线程因为异常退出? 多核利用 var http = require('http'); • 提升稳定 仿若熟悉的Web Worker: child_process 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
  20. 20. 小结 • 异步编程问题?EventProxy、JScex 等 • 内存限制问题?第三方存储Redis • CPU消耗问题?缓存中间结果 • 单线程CPU利用不足问题?多进程 • 单线程稳定性问题?Node-Cluster 20
  21. 21. 实践:运维 • 异常 // 异步方法中try catch是不靠谱滴 双机房 // 异步方法的异常 进程数量 • 日志 双Redis MRedis模块 async(function (err, data) { CPU 双MongoDB MongoSkin 内存 { if (err) • 监控 数据源集群 Loadlogger.error(err); 磁盘IO // TODO return; • 部署 流量} // TODO }); • 备份容灾 21
  22. 22. 实践:测试 • 测试 • 单元测试 • 自动化测试 • 性能测试 Should.js • 持续集成 WebGhost 22
  23. 23. 实践:CommonJS & Node & NPM CommonJS NPM Node 23
  24. 24. 实践:公司范围内共享代码 • 如何保护隐私代码 • 如何重用散乱代码 • 如何告别复制粘贴 24
  25. 25. 实践:公司范围内共享代码 单向同步 本地NPM 官方NPM 私有模块 项目 公有模块 25
  26. 26. 展望 • 深度发掘前端开发和用户体验 • 无需与开发沟通,节省成本 • 知晓细节,更易改进产品体验 • 感谢伟大的github • 感谢伟大的NPM促成的生态圈 • 感谢Node这件美妙的礼物 26
  27. 27. Q&A 屌丝のぎゃくしゅう 27

×