自从 Vue2 出正式版后, 就开始了 SSR 之旅, 不过之前用的都是虚拟主机, 部署不了 SSR, 所以也只是在本地写着玩, 双 11 的时候, 买了个某云主机, 正式开始了 SSR 之旅, 然后过程并不顺利, 部署, 运行都没问题, 但是发现内存泄漏严重, 1核1G内存的主机根本负担不了, 没什么访问量的情况下, 几个小时的时间, 1G 内存就用光, 明显有很严重的内存泄漏, 在本地环境压测, rps(每秒请求数) 无限接近于 1, 在云服务器更是压测都完成不了, 于是开始了优化之旅
经过查资料和测试, 发现 axios 和 vue-meta 都有内存泄漏之嫌
之前有写过一篇 Vue2 SSR渲染, 如何根据不同页面修改 meta? , 既然这个有内存泄漏的嫌疑, 只好先把代码恢复回去
axios 的拦截器在 node 端也会导致内存泄漏, 因为之前版本是 SPA 版的, axios 配置也是针对 SPA 的配置, 里面有用到拦截器, 并且有大量的逻辑处理在里面, 包括加载进度, 错误处理等等, 这些逻辑在 node 端是没有任何意义的, 那么我们就需要对 node 端写个专门的 axios 配置文件
api/index-server.js (server端)
https://github.com/lincenying...api/index-client.js (client端)
https://github.com/lincenying...缓存主要包括两个部分:
服务端的 api 数据缓存
组件的缓存
昨天已经写了一篇文章: Vue2 SSR 缓存 Api 数据 , 这里不再多说, 上面 axios 服务端配置文件中, 也有相关代码
首先先安装 lru-cache
然后在 server.js
里 createBundleRenderer
的时候带上缓存的配置
require('vue-server-renderer').createBundleRenderer(bundle, { cache: require('lru-cache')({ max: 1000, // 缓存最大数量 maxAge: 1000 * 60 * 15, // 缓存时间 15分钟 }) })
在组件里申明 key
serverCacheKey: () => { return `aside::account` }
组件缓存的相关用法, 请参考官方文档:
https://github.com/vuejs/vue/...注意: 一般情况下, 我们不要给容器型组件, 只给展示型组件加缓存, 如一个组件是静态组件, 如组件的数据是通过 props 传进去的
一般情况我们都需要用 nginx 或者 apache 做端口转发,
server { listen 80; server_name mmxiaowu.com www.mmxiaowu.com ssr.mmxiaowu.com; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Nginx-Proxy true; proxy_set_header Connection ""; proxy_pass http://127.0.0.1:8080; } }
我们可以修改下配置文件, 让静态文件直接走 nginx, 不再经过 nodejs
server { listen 80; server_name mmxiaowu.com www.mmxiaowu.com ssr.mmxiaowu.com; location ~ ^/(static|upload)/ { root /your/webroot/mmf-blog-vue2-ssr/dist; expires 30d; } location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Nginx-Proxy true; proxy_set_header Connection ""; proxy_pass http://127.0.0.1:8080; } }
经过以上一些优化后, 再进行一次压测:
E:/web/webpack/mmf-blog-vue2-ssr>loadtest -n 2000 http://localhost:8080/ [Sat Dec 31 2016 14:12:17] INFO Requests: 0 (0%), requests per second: 0, mean latency: 0 ms [Sat Dec 31 2016 14:12:22] INFO Requests: 246 (12%), requests per second: 49, mean latency: 20.3 ms [Sat Dec 31 2016 14:12:27] INFO Requests: 508 (25%), requests per second: 52, mean latency: 19 ms [Sat Dec 31 2016 14:12:32] INFO Requests: 773 (39%), requests per second: 53, mean latency: 18.8 ms [Sat Dec 31 2016 14:12:37] INFO Requests: 1036 (52%), requests per second: 53, mean latency: 19 ms [Sat Dec 31 2016 14:12:42] INFO Requests: 1296 (65%), requests per second: 52, mean latency: 19.2 ms [Sat Dec 31 2016 14:12:47] INFO Requests: 1548 (77%), requests per second: 50, mean latency: 19.9 ms [Sat Dec 31 2016 14:12:52] INFO Requests: 1776 (89%), requests per second: 46, mean latency: 21.8 ms [Sat Dec 31 2016 14:12:57] INFO [Sat Dec 31 2016 14:12:57] INFO Target URL: http://localhost:8080/ [Sat Dec 31 2016 14:12:57] INFO Max requests: 2000 [Sat Dec 31 2016 14:12:57] INFO Concurrency level: 1 [Sat Dec 31 2016 14:12:57] INFO Agent: none [Sat Dec 31 2016 14:12:57] INFO [Sat Dec 31 2016 14:12:57] INFO Completed requests: 2000 [Sat Dec 31 2016 14:12:57] INFO Total errors: 0 [Sat Dec 31 2016 14:12:57] INFO Total time: 39.933183222 s [Sat Dec 31 2016 14:12:57] INFO Requests per second: 50 [Sat Dec 31 2016 14:12:57] INFO Mean latency: 19.9 ms [Sat Dec 31 2016 14:12:57] INFO [Sat Dec 31 2016 14:12:57] INFO Percentage of the requests served within a certain time [Sat Dec 31 2016 14:12:57] INFO 50% 16 ms [Sat Dec 31 2016 14:12:57] INFO 90% 27 ms [Sat Dec 31 2016 14:12:57] INFO 95% 43 ms [Sat Dec 31 2016 14:12:57] INFO 99% 57 ms [Sat Dec 31 2016 14:12:57] INFO 100% 133 ms (longest request)
效果非常不错, rps 已经能达到 50 了, 内存使用也大弧度下降了, 不过在云服务器上依然不够理想, 因为可能是云服务器上数据比本地的多, 另外云服务器的配置太烂...但是随着运行时间的增加, 内存肯定也会上升, 毕竟缓存也是需要占用内存的, 不过这个是属于合理开支...
过了差不多一天的时间, 内存只涨了 7M 左右...