Node 在淘宝的应用实践


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

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

霸气虎风

贡献于2012-10-19

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf