node.js,mongodb,redis,关于ubuntu在生产中的性能下降,RAM是免费的,CPU 100%

正如问题标题所暗示的那样,我很难弄清楚在我的应用程序上可以改进什么(或者在os,ubuntu中进行调优)以获得可接受的性能。 但首先我要解释一下架构:

前端服务器是8核心机器,运行Ubuntu 12.04的8个内存。 该应用程序是完全用JavaScript编写的,运行在node.js v 0.8.22(因为一些模块似乎抱怨新版本的节点)我使用nginx 1.4来代理从端口80和443的httpstream量到8个受pipe理的节点工作人员并开始使用节点群集api。 我使用最新版本的socket.io 0.9.14来处理websocket连接,在这个连接上我只启用了websocket和xhr-polling作为可用的传输。 在这台机器上,我也运行一个Redis实例(2.2)

我将持久性数据(如用户和分数)存储在mongodb(3.6)上的第二台服务器上,并带有4个内存和2个内核。

这个应用程序在几个月前就开始投入使用(直到几个星期前它已经在一个盒子里运行),每天大约有18k个用户在使用它。 除了一个主要问题之外,它一直运行得非常好:性能下降。 随着使用,每个进程使用的CPU的数量增长,直到它统一工作人员(这将不再服务请求)。 我暂时解决了每分钟检查每个工作人员使用的cpu,如果达到98%,重新启动它。 所以这里的问题主要是CPU,而不是RAM。 内存不再是一个问题,因为我已经更新到socket.io 0.9.14(早期版本泄漏内存),所以我怀疑是一个内存泄漏的问题,尤其是因为现在是CPU快速增长(我必须每天重新启动每个工人10-12次!)。 在使用中的RAM也是老生常谈,但是每2-3天使用一次就很慢,奇怪的是即使我彻底重新启动整个应用程序也不会释放。 只有重新启动服务器才会被释放! 这我真的不明白…

我现在已经发现了非常棒的nodefly ,所以我终于可以看到我的生产服务器上发生了什么事情,而且我正在收集数据。 如果有人想看看我可以给你的图表,但基本上我可以看到我有80到200个并发连接! 我期待node.js处理数千个,而不是数百个请求。 另外,httpstream量的平均响应时间在500到1500毫秒之间浮动,我认为这真的是很多。 另外,在这个有1300个在线用户的时刻,这是“ss -s”的输出:

Total: 5013 (kernel 5533) TCP: 8047 (estab 4788, closed 3097, orphaned 139, synrecv 0, timewait 3097/0), ports 0 Transport Total IP IPv6 * 5533 - - RAW 0 0 0 UDP 0 0 0 TCP 4950 4948 2 INET 4950 4948 2 FRAG 0 0 0 

这表明我在等待中有很多closures的连接。 我已经增加了最大打开文件为999999,这里是ulimit -a的输出:

 core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 63724 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 999999 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 63724 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 

所以我认为问题可能出在HTTPstream量上,由于某些原因导致可用的端口/套接字(?)饱和,但是有一件事对我没有意义:为什么当我重新启动工作者,并且所有的客户端在几秒钟内重新连接时,工人CPU上的负载下降到1%,能够正常提供服务,直到大约1小时后(在高峰时间)饱和为止。

我主要是一个JavaScript程序员,而不是一个系统pipe理员,所以我不知道应该用我的服务器处理多less负载,但肯定不是它应该执行的。 该应用程序是稳定的,否则,这最后一个问题是阻止我发布的应用程序的移动版本准备好了,显然他们会带来更多的负载,并最终崩溃整个事情!

希望有一些明显的,我做错了,有人会帮助发现它…随时向我要求更多的信息,我很抱歉的问题的长度,但有必要我相信…提前致谢!

经过几天激烈的试验和错误,我很高兴能够说,我已经明白了瓶颈所在,我会在这里张贴,以便其他人可以从我的发现中受益。

问题出在我使用socket.io的pub / sub连接,特别是socket.io使用的RedisStore来处理套接字实例的进程间通信。

在意识到我可以使用redis轻松实现我自己的pub / sub版本之后,我决定尝试一下,并从socket.io中移除redisStore,留下默认的内存存储(我不需要广播到所有连接的客户端,但只有两个不同的用户可能在不同的进程连接)

最初,我宣称只有2个全局的redis连接x处理每个连接的客户端上的pub / sub,并且应用程序使用较less的资源,但是我仍然受到CPU使用率持续增长的影响,所以没有太大改变。 但后来我决定尝试为每个客户端创build2个到redis的新连接,以便仅在他们的会话中处理他们的pub / sub,然后在用户断开连接后closures连接。 然后经过一天的生产使用,cpu仍然在0-5%…宾果! 没有stream程重启,没有错误,我期待的性能。 现在我可以说,node.js岩石,并高兴地select它来build立这个应用程序。

幸运的是,redis被devise为处理许多并发连接(不同的是mongo),默认情况下它设置为10k,为一个大约5k个并发用户留下空间,在单个redis实例上,这对我来说暂时足够了,已经读了它可以推到64k并发连接,所以这个架构应该足够坚实,我相信。

在这一点上,我想实现某种连接池redis,进一步优化它,但不知道这是否不会再引起pub / sub事件build立在连接,除非他们每个人每次都被毁坏和重新创build,以清除它们。

无论如何,谢谢你的回答,我会好奇的知道你的想法,如果你有任何其他的build议。

干杯。

你有一些源代码转储? 它可能是连接到数据库没有closures? 等待HTTP连接的进程永远不会closures。

你可以发布一些日志?

做一个ps -ef,确保没有任何东西在运行。 我已经看到web进程留下僵尸,不会死,直到你杀死-9。 有时关机不起作用或不能完全工作,这些线程或进程将持有RAM,有时CPU。

它可能是代码中的某个无限循环,或者是一个在数据库连接上的崩溃进程。

什么NPM模块正在使用? 他们都是最新的?

你在捕捉exception吗? 请参阅: http : //geoff.greer.fm/2012/06/10/nodejs-dealing-with-errors/请参阅: https : //stackoverflow.com/questions/10122245/capture-node-js-crash-reason

一般提示:

http://clock.co.uk/tech-blogs/preventing-http-raise-hangup-error-on-destroyed-socket-write-from-crashing-your-nodejs-server

http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever

http://hectorcorrea.com/blog/running-a-node-js-web-site-in-production-a-beginners-guide

https://stackoverflow.com/questions/1911015/how-to-debug-node-js-applications

https://github.com/dannycoates/node-inspector

http://elegantcode.com/2011/01/14/taking-baby-steps-with-node-js-debugging-with-node-inspector/

本身并不是一个答案,因为你的问题更多的是一个故事而不是一个答案的提出问题。

只是为了说明我成功构build了一个带有socket.io的node.js服务器,处理了超过100万个持续连接,消息有效负载平均为700字节。

networking接口卡在1Gbps时开始饱和,我看到很多I / O等待从发布事件到所有客户端。

从代理angular色中删除nginx也返回了宝贵的内存,因为只有一台服务器达到一百万个持久连接,调整configuration,应用程序和调整操作系统参数是一项艰巨的任务。 请记住,它只适用于大量的RAM(大约1M个websocket连接大约16GB的RAM,使用node.js,我认为使用sock.js对于低内存消耗是理想的,但是现在,socket.io消耗那么多)。

这个链接是我的出发点,达到与节点的连接量。 除了它是一个Erlang应用程序,所有的操作系​​统调优几乎都是应用程序不可知的,应该被那些针对大量持久连接(websockets或long-polling)的人使用。

HTH,