Silence & Solitude makes...

Pu's mind space

一次搭建高性能Nodejs httpServer的尝试(2)

继续上次的.
上次搞的node http server,一个简单的服务器,接收HTTP POST,解析数据入mongo库(nodejs driver用的native driver而非mongoose),主要做了下面的一些优化:

  • 系统层面放开同时打开的文件数(也就是socket数)的限制
  • 复用链接(主要是ab http1.0 keepalive的坑)
  • 增加并发
  • “优化”业务逻辑

其实都是一些”预”优化,在没有需要针对处理的问题出现的情况下先放开一些东西. 后来测试结果满意,一个小项目开始,两周完成了一个小业务之后,需要部署让测试介入.环境一换,问题就来了.

原先在本地的Linux台式机上近16000的TPS到了openstack(4core, 4GB memory)的VM上TPS瞬间掉到了小几千.赶紧登陆上去vmstat查看,发现Procs的r值(等待执行的进程数)接近20,远大于CPU核心数,也就是说CPU成了应用的瓶颈.–原来台式机是8X3.4GHz,到了虚拟机上只有4X2.3GHz,早该想到!

提高虚拟核心数!当然同时也把node.js的slave process提高到8个.同时,把libuv的线程池的限制也放开(设置UV_THREADPOOL_SIZE=8的环境变量),至于这个有没有用,其实我也是不太清楚的,顺便贴一个关于这个问题的争论—好吧,其实是撕逼,吃瓜群众表示看神仙打架也很有意思嘛—也不知道libuv团队最后有没有采纳这个不礼貌的家伙的建议.但是不管libuv的线程池是否应该跟核心数相等,个人觉得不管怎么说,mongodb的native driver开的线程池的大小是5,如果libuv的线程池大小只有4的话肯定不能发挥出其期待的性能吧.再次顺便提一句,mongodb nodejs官方的driver其默认线程池大小也是可以改的–详见参考文档,但是我这里并没有尝试.

好吧,再次测试,TPS又恢复到了16000+. Done!

之后又简单看了一下GC/内存有没有潜在的问题,这也是上一篇文末希望做的.简单来讲做法就是使用node-inspector+Chrome DevTools来比对heap snapshot(和参考文章的工具小有差异)以及使用–trace_gc来查看请求量大量/持久的压力下GC的时间是否能够接受.
但是由于压力较小,没能发现什么—于是就草草地交给测试了.

希望这个DEMO项目能做下去,这样之后说不定在使用中真的就能碰到大数据量的情况,来真正被需求倒逼去进一步探索其他的性能瓶颈—作为一个敏捷开发者(傲娇),我们不提倡提前优化,哈哈.