问题
最近在公司维护nuxt项目时,线上遇到了一个问题——访问网站,网站会报502或者JS、css资源报502。
去运维那一查pm2,项目node服务器的CPU达到了100%,实际上这段时间并没有人访问,那是为什么CPU会100%从而导致node服务器无法正常运行?
分析
太多的分析就不说了,期间向几个方向都排查过:
- nuxt社区有人说是nuxt框架问题,某些版本会出现node服务端内存泄漏。
- 第三方组件未在destroy时进行释放,或者事件监听,页面关闭后未解绑事件。
- 代码的书写问题,闭包引起的内存泄漏。
- 用谷歌浏览器工具分析网站内存使用情况,发现大量Vue.component组件未释放。
- 官网说SSR最好不要使用
Vue.use()
和Vue.component(),这会导致内存泄漏(官网链接)。
我们可以得出大概率是node服务端内存泄漏,导致CPU缓慢升高,每请求一次网站页面都会造成重复的代码块积累在服务端,并且不会释放。
解决
我们找到项目中使用Vue.use()的地方,并打log查看。
import Vue from 'vue'
import Errors from '@/components/custom/Errors'
export default () => {
Vue.use(Errors)
console.log(Vue, 'logVue');
}
多次刷新页面,我们可以看到在控制台看到node服务端的log情况。搜索Errors,有大量重复的Errors组件,实际上只需要一个Errors组件就够了。
找到了问题,接下来就好办了。在Vue.use() 注册时检查服务端是否注册过,如果注册过,就不再注册:
import Vue from 'vue'
import Errors from '@/components/custom/Errors'
export default () => {
if (Vue._use_components) {return}
Vue._use_components = true
Vue.use(Errors)
console.log(Vue, 'logVue');
}
可以看到打印出来的log,多次刷新请求服务器,Errors组件也不会被多次注册了。
总结
1、用到第三方组件在页面生命周期结束前destroy释放,
2、事件监听,生命周期结束前解绑事件。
3、接下来只需要将用到 Vue.use()和Vue.component()地方的代码加上判断优化。
4、冗余保护:因为我们的CPU设置的是1024M,所以我们在pm2加上:
"max_memory_restart": "1000M"
如果CPU达到1000M内存阈值,则重新启动。
优化后项目CPU运行情况: