AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

Node.js高并发聊天服务实战 by 王文明@360

发布者 noder
发布于 1434062972359  浏览 11418 关键词 Node.JS, 并发 
分享到

第1页

Node.js⾼高并发聊天 服务实战

⺩王⽂文明 Github: wangwenming

2015-03-28



第2页

⼤大纲

背景 技术选型&极简架构 性能优化⼯工具



第3页

背景

产品:

• http://www.haosou.com/s?q=exo&src=node • http://t.haosou.com/chat/tantanmobile?topic=exo • http://xiaohua.hao.360.cn/daojie 点进去再滚到底部 • http://tantan.360.news.ifeng.com/news?nid=54d82f5ca15903ec558b4568#_zbs_360_tantan • 世界杯期间 cntv 直播⻚页⾯面

数据:

• 同时在线约 100万 • 每秒接⼊入连接数 5000 • 最⼤大的⼀一个Topic有10万⼈人 (m) • 每秒⼲⼴广播消息 20条 (n) • 每秒⼲⼴广播消息数 200万条 (m * n)



第4页

技术选型

⻓长连接

Q1: ⻓长连接、轮询?

• 举个例⼦子:微博PC版,有2个: 1. 30S⼀一次的轮询(push_count) 2. im的WebSocket

Q2: ⻓长连接⽅方案

• Flash (双向通信) • .WWeebbSSocket (双双向向通通信信))rfrcfc6644555(2(021011.11.21)2,),⼿手⼿机手机上上混合混开合发开⽆发无法⽆无跨法域跨 域

fayyee--wweebbssoocckkeet@t@00.7.7.2.2(w(webesboscokcekt-edtr-idvreirv@er0@.50.3.5) .3) 66445555在在⼿⼿手手机机上上的的⽀⽀支持支持AAndnrdoriodi>d=>4=.44.M4 oMboilbeiSleafSaarif>a=ri6>.=06.0 • .LLoonnggPPuullll xhr stream•ing (rexshprosntrseeaTemxitn⾮g非⼀(r一e次sp返on回se,Teoxntre⾮a非d⼀y一s次ta返tec回ha,ngoen,rexahdr.yrestaadtyeScthaaten=g3e),Cxhhror.mreeadFiyrSeftoaxte=3) Chrome Firefox Forever F•rame(ifFraomreeve/ rHFTrTamP 1e(.1ifrCamhuenk/ eHdTETnPco1d.1inCg)hIuEn,k但ed是E会nc⼀o一d直inLgo)aIdEi,ng但是会⼀一直Loading HTMLFile•(ActivHeXTOMbLjFeiclet对(A象c)tiveXObject对象) JSONP,•Old IE下JSO要N跨P域,Old IE下要跨域 • 兼容性⼀一栏 • “Even Faster Web Sites: Performance Best Practices for Web Developers”



第5页

技术选型

⻓长连接框架

https://github.com/sockjs/sockjs-node Star: 900 @0.3.15

https://github.com/Automattic/socket.io/ Star: 16, 134 @1.3.2 

1. #438 2011-08-01提出,作者rauch在2014-08-19关闭了这个 issue,也没有解决,有301个讨论 2. socket.io 的封装功能更多,包括Redis,消息的封装等 on(‘任意’) emit(‘任意消息’),SockJS有且只有1个 on(‘message’) 3. IP地址获取: x-forwarded-for sockjs/lib/transport.js:159

$ mocha test/echo-server.js



第6页

服务架构

尽量简单的架构

Master



T SlaveT

T1 T2 AB



C SlaveC

C1 C2 CD



第7页

服务架构

再简单⼀一点

http://en.wikipedia.org/wiki/Publish %E2%80%93subscribe_pattern

RedisManager.js

hmdel ping retry

数据结构 Hash - hmget hdel Set - sadd srem publish psubscribe 使⽤用O(N)复杂度的操作 ⼤大数据操作使⽤用cursor



第8页

LVS:80



服务架构

部署



Nginx:x.x.x.1-2



Node:900[1-3]



Redis



第9页

$ mocha test/chat-server.js

http://localhost:8080/tantan/chat-client.html?ui

> socket.post(new Date()); > setInterval(function() {socket.post(new Date());}, 2000);



第10页

性能优化

Chrome DevTools



第11页

性能优化

v8

$ d8 —prof --log-timer-events script.js # ⽣生成 v8.log $ mac-tick-processor v8.log $ plot-timer-events v8.log # 需要 Linux with gnuplot 4.6 来绘图

$ npm install -g tick $ node-tick-processor v8.log

http://v8.googlecode.com/svn/branches/bleeding_edge/tools/profviz/profviz.html



第12页

性能优化

v8-profiler

$ npm install v8-profiler $ npm install -g node-inspector $ node --prof --prof_lazy --log index.js 9011 /profile # 会⽴立即⽣生成⼀一个没有真实数据的 v8.log $ node-debug --web-port 8888 index.js 9011 /profile

语句上的优化: http://s3.mrale.ph/nodecamp.eu/#12



第13页

性能优化

压缩数据包

JSON是⽐比较冗余的,可从⽂文本上压缩

$ mocha test/unserialize.js 匿名压缩⽐比: 30.8%, 253B ==> 78B 登录压缩⽐比: 40.3%, 258B ==> 104B

GZIP压缩

Gzip有收益的建议最⼩小值是150-1000字节,150字节左右压缩了反⽽而会变⼤大

如果不考虑旧浏览器,可以直接使⽤用ArrayBuffer

Redis操作: O(m,n) => O(n)

strace(DTrace) -> $ sudo dtruss -cnp 29663  strace发现80%操作在 epoll_wait (只有1个线程)



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。