mongose提升性能

106 阅读3分钟

最近的一直进行的工作包括提升mongo的性能,在我接手的这段时间里,在newrelic上的平均响应时长是200-300ms,遇到任务堵塞还会暴涨到600ms左右一小段时间。

第一次

尝试是升级mongoose@4.4.9,效果是很明显的,响应时长立马降下来了,平均响应时长100ms左右。但,我们观察到mongo的连接数直接升了一倍,app进程在阶段性重启,大约是20分钟一次,因为我们用pm2的时候,设置了最大内存,一旦超过就自动重启,于是我们放弃了。

期间给mongo-core改了一个问题,如果使用readReference=secondaryPreferred的话,如果监听的是open事件的话,立马开始读数据库则所有的请求都会到master上面去。看了代码之后,我尝试监听fullsetup事件,但请求只会到master以及一个secondary上面去。

于是我改代码,我把'all'事件给暴露出来了,于是当监听all事件的话,就能均匀分布到所有的节点上门去了。当然了,这种情况只会在这种特殊情况下出现。

同时呢,还有另一个问题,就是连接数爆的问题,这真是它的bug,我那天刚给它改了,等我想提交的时候,作者自己改了,因为这问题不止我一个人发现。目前最新的mongoose@4.4.12已经没有这个问题了。其实响应时长降低的原因就在于几乎是每一个请求就会被分配一个连接,所以连接数非常多,响应快,但是代价是内存泄露以及连接数爆棚。

第二次

调整连接参数,调整了连接池以及keepAlive的数值。

第三次

尝试升级到mongoose@3.8.39,顺利,响应时长有小幅度的下降。但是当时又出现了一个问题,其中一个数据库的连接数很高,TCP TIME_WAIT是Established的两倍,然后会几个小时就暴增一次,于是nodejs进程出现大量fail connect错误,整体响应时长也暴增。

另外,3.8.394.4.12的对比效果不明显,反而是3.8.39的效果稍好一些

第四次

经过了第三次,我突然想到,数据库本身是不是有问题,我看了下数据库版本,3.0.3,然后去官网一查,我去,果然有问题!其中刚好就是这个版本,有一个复制集中任务阻塞的bug,在3.0.4中修复了docs.mongodb.org/manual/rele…

于是安排运维升级,升级到最新的3.2版本,运维说不行,没法直接升级,于是用export与restore,但是之后无法加入集群,具体原因不清楚,以后再查,先升级要紧,于是改3.0.11,顺利升级。

戏剧般的效果出来了,响应时长瞬间将至40ms左右,升级的那台数据库的CPU与查询数瞬间暴涨,但是任务数却没怎么升高,连接数正常,其他数据库的查询几乎没有了,也就是说,这一台数据库就几乎抗住了所有的查询。后来陆续升级了,目前一切正常。

这结果,我梦里都能笑出来,目前性能提升10倍左右,平均响应时长30ms,newrelic的apdex指数文档在0.98,之前是0.7-0.9。

两点教训

一、很多性能问题还是得靠升级解决;
二、性能问题要从基础开始排查;

后记

我深知基础设施的改进能带来多大的改变,量变产生质变,你能比竞争对手快10倍就意味着你领先非常多了,对于我们来说,性能决定了我们能承载多少用户,能活多久。对于团队发展到一定程度之后的技术债务,尽早还清,所以也希望能分清团队里重要与紧急的任务。