Myfox on NodeJS
Upcoming SlideShare
Loading in...5
×
 

Myfox on NodeJS

on

  • 5,493 views

5月14日nodeparty杭州站上的演讲

5月14日nodeparty杭州站上的演讲

Statistics

Views

Total Views
5,493
Views on SlideShare
4,464
Embed Views
1,029

Actions

Likes
13
Downloads
129
Comments
0

7 Embeds 1,029

http://cnodejs.org 969
http://club.cnodejs.org 45
http://xianguo.com 8
http://club.cnodejs.net 3
http://localhost 2
http://cache.baidu.com 1
http://km.oa.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Myfox on NodeJS Myfox on NodeJS Presentation Transcript

  • MyFOX On NodeJS 张轩丞(朋春) pengchun@taobao.com 新浪微博:@我是aleafs
  • 关于NodeJS
  • 服务器端的JavaScript□ Google V8引擎 □ 单线程,高性能 • 属性访问优化 • 缓存机器码 • 垃圾回收□ libev □ 事件机制□ libeio □ 非阻塞异步IO
  • 性能:Socket □ 远程Memcache □ 长连接 □ 50连接池
  • 性能:HTTP□ QPS:4392 □ GC更频繁
  • 什么是MyFOX
  • 什么是Myfox 数据 云梯 魔方 MyFOX 数据装载 数据查询 存储 集群 MyISAM
  • SQL示例:SELECT IF(INSTR(f.keyword, ) > 0, UPPER(TRIM(f.keyword)),CONCAT(b.brand_name, ,UPPER(TRIM(f.keyword)))) AS f0, SUM(f.search_num) AS f1, SUM(f.uv) AS f2, ROUND(SUM(f.search_num) / SUM(f.uv), 2) AS f3, ROUND(AVG(f.uv),2) AS f4FROM dm_fact_keyword_brand_d fINNER JOIN dim_brand b ON f.keyword_brand_id = b.brand_idWHERE f.keyword_type_id = 1 AND f.keyword != AND keyword_cat_id IN (50002535) AND thedate <= 2011-05-10 AND thedate >= 2011-05-08GROUP BY f0ORDER BY SUM(f.search_num) DESC LIMIT 0, 100
  • 查询过程路 APC SQL解析由层 缓存 语义理解 查询路由 字段改写 分片SQL 计算规则查询 缓存 取分片数据层计 结果合并算层
  • 语义理解WHERE thedate <= 2011-05-10 AND thedate >= 2011-05-08 AND f.keyword != AND keyword_cat_id IN (50002535) dm_fact_keyword_brand_d 2011-05-08 3 # dm_fact_keyword_brand_d_0.t_686_280 ... 2011-05-09 2 # dm_fact_keyword_brand_d_0.t_3b8_300 ... 2011-05-10 8 # dm_fact_keyword_brand_d_0.t_3ac_293 ...
  • 字段改写 SELECT a AS f0, SUM(f.search_num) AS f1, SUM(f.uv) AS f2, ROUND(SUM(f.search_num) / SUM(f.uv), 2) AS f3, AVG(f.uv) AS f4□ AVG(f.uv)□ 1 + SUM(aa)□ SELECT a FROM … ORDER BY b□ 重复查询列
  • 取分片数据□ 困难 查询SQL • 分片SQL很多 • PHP单线程 • MySQL查询阻塞 nginx drizzle□ 异步并发 • nginx + drizzle • http协议,curl_multi_get mysql • JSON格式
  • 结果合并□ 局部有序,局部最优□ 无聚合字段 • 二路归并 • LIMIT运算□ 有聚合字段 • 聚合规则处理(SUM,MAX,MIN,DISTINCT) • 表达式求值 • 堆排序 • LIMIT运算
  • 小结:什么是Myfox?□ 中间层 □ 特点: • 被机器访问 • CPU密集 • 功能单一 • 无文件IO • 数据只读
  • 为什么要Node化?
  • Why?□ 兴趣,推劢社区发展□ 榨干CPU,提高并发能力□ 简化部署□ 使用连接池□ 请求状态共享
  • 简化部署[pengchun]$ cd ${nginx} && ./configure --add-module=../drizzle-nginx/ --add-module=../rds-json-nginx/ --add-module=../nginx-form-input/ --add-module=../nginx-devel-kit/ --add-module=../nginx-set-misc/[pengchun]$ cat ./nginx.conf location /mysql_06_02 { charset utf-8; set_form_input $sql __SQL__; set_unescape_uri $sql $sql; drizzle_query $sql; drizzle_pass cluster_node_06_02; rds_json on; }
  • 使用连接池[pengchun]$ netstat –at | wc –l25694[pengchun]$ netstat –at | grep –c ‘TIME_WAIT’13106[pengchun]$ cat /etc/sysctl.confnet.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_fin_timeout = 30[pengchun]$ tail ~/logs/mysql.log2011-04-28 16:41:44 WARNING CONNECT_ERROR -{"host":“**","port":3306,"user":“**","pass":"3*******2","error":"Cantconnect to MySQL server on 172.23.*.* (4)“}
  • 请求状态共享
  • 那么,关注什么?□ 分层设计□ 连接管理□ 稳定性□ 数据缓存
  • 分层设计
  • 为什么要分层?□ 利用多核□ 提高并发能力 • “工作量大的地方多派几个人”
  • 分层逻辑
  • master□ 启劢worker和router□ 心跳检测□ 监听端口对外服务□ 权限控制□ 请求转发给worker
  • master:压测□ HTTP接口□ RH5.4, 6G MEM, 4 * 2.2 GHz CPU□ node 0.4.0, siege2.70并发 CPU占用 RT QPS600 96% 0.05 1116700 92% 0.08 1225800 87% 0.18 1227900 82% 0.28 12031000 81% 0.36 1157
  • worker□ 向router要路由□ 取分片数据□ 结果汇总计算□ 分布式缓存管理
  • router□ 加载路由到内存□ SQL解析□ 字段改写□ 查”路由表”□ SQL重新生成
  • 连接管理
  • 连接池□ mysql□ memcachevar mpool = require(../../lib/pool.js).create(2);mpool.get(function(conn, pos) { // xxx: blabla mpool.release(pos);});mpool.close();
  • 连接池get : function(callback){ if (this.stoped) { return; } this.queue.push(callback);},release : function(id) { this.stack.push(id);},while (this.queue.length > 0 && this.stack.length > 0) { var id = this.stack.pop(); var cb = this.queue.shift(); cb(this.conn[id], id); delete cb, id;}
  • PIPE□ Unix socketpair□ Heartbeat master□ 请求转发 router worker
  • 稳定性
  • 异常处理process.on(uncaughtException, function(err) { console.log(Error : + err); // 告警 process.exit(1);});[pengchun@edp2 bin]$ nohup ./supervise ${nodefox-dir} & http://cr.yp.to/daemontools/supervise.html
  • 捕捉信号this.dispatcher.sigaction(SIGHUP, function() { // 忽略HUP信号});this.dispatcher.sigaction(SIGTERM, function() { _self.block = true; // 优雅退出 process.exit();}// …
  • 心跳检测□ master -> worker□ master -> router-> Hello<- 我还有11个没处理
  • 任务分配□ “闲”者多劳
  • 数据缓存
  • 两种缓存 分布式缓存 本地缓存存储介质 memcache 本地内存数据量 大 小共享范围 多机共享 进程独享使用者 worker router存储数据 分片SQL、最终结果 路由表
  • 本地缓存var Caches = {};var Lcache = function(key, ttl) { this.prefix = key.toString().trim(); this.expire = ttl;}Lcache.prototype.set = function(key, val, ttl) { Caches[this.prefix + key] = { v: val, t: time() + (empty(ttl) ? this.expire: ttl), };}
  • 可能的问题var http = require(http);var counter = 0;var restime = 0;var cache = require(../../lib/cache/lcache.js).create( benchTest, 3600);http.createServer(function (req, res) { var tm1 = time(); cache.set(++counter, { i : counter, t : blabla...., }); res.writeHead(200, {Content-Type: text/plain}); res.end(!--STATUS OK--n); var tm2 = time() - tm1; restime = restime < tm2 ? tm2 : restime;}).listen(8346, "127.0.0.1");
  • 可能的问题(续)console.log(numtheapTotaltheapUsedtrsstvsizetrt);var mem = process.memoryUsage();setInterval(function() { mem = process.memoryUsage(); console.log(counter + t + mem.heapTotal + t + mem.heapUsed + t + mem.rss + t + mem.vsize + t + restime); restime = 0;}, 1000);[pengchun@edp2 bin]$ ./siege -c1000 127.0.0.1:8346
  • 可能的问题(内存) Memory Used (from 201 ~ 300 s) 200 900MB MB 180 800 160 700 140 600 120 500 100 400 80 300 60 200 40 20 100 0 0 heapTotal heapUsed rss vsize
  • 可能的问题(堆内存) Memory Used (Interval 6 senconds) 200 1G 700MB 千 180 600 160 140 500 120 400 100 300 80 60 200 40 100 20 0 0 Heap Total Item Count
  • 可能的问题(响应时间) Response Time (from 201 ~ 300 s)ms 70 60 50 40 30 20 10 0 -10 response time
  • 改进□ 目标: □ 方案: • 内存可控 • 摒弃本地缓存? • 规避GC • B+ Tree with Buffervar buffer = new Buffer(1024 * 1024 * 200);var http = require(http);var counter = 0;http.createServer(function (req, res) { counter++; res.writeHead(200, {Content-Type: text/plain}); res.end(!--STATUS OK--n);}).listen(8346, "127.0.0.1");
  • With Buffer Memory Used (with Buffer) 80 1000MB 百万 900 70 800 60 700 50 600 40 500 400 30 300 20 200 10 100 0 0 heapTotal heapUsed rss items count * 500 vsize
  • Thanks