Vue+Koa2+mongoose写一个像素绘板的实现方法(3)

const mongoose = require('mongoose') let schema = new mongoose.Schema({ index: { type: Number, index: true }, r: Number, g: Number, b: Number }, { collection: 'dots' })

index 代替 x & y 以及移除 rgba 中的 a 在代码中再补上,都能显著降低 collection 的实际存储大小

在测试过程中其实还有个特别奇怪的问题,就是单核小霸王服务器上,我如果一次性取出所有数据存储到一个 Array 中,程序会在中途奔溃,没有任何报错信息。起初我以为是 CPU 满荷载久了导致的奔溃(top 查看硬件使用信息),所以还特意新租了一个服务器,想用一个群里的朋友提醒的“分布式”。再后面一段时间,我通过分页取数据,发现程序总是在取第二十万零几百条(一个固定数字)是陡然奔溃,所以为 CPU 证了清白。

PS:好在以前没分布式经验,不然一条路走到黑,可能现在都还以为是 CPU 的问题呢。

数据传输思考历程

上面有提到过,长度为 1,572,864 的颜色数组占用内存为 1.5M ,我猜想数据传输时也是这个大小。起初我想,我得把这个数据压缩压缩(不是指 gzip ),但由于不会,就想到了替代方案。前面已经为了避免取数时高额的 IO 消耗,会在内存中存储一个数据副本,我想到这个数据我可以通过拼接(1.1 的结构相对而言 CPU 消耗少得多)生成 ImageData 再通过 ctx.putImageData 画到 Canvas 上,这就是关键之二把数据副本画在服务器上的一个 canvas 上。

然后就好办了,可以通过 ctx.toDataURL || fs.writeFile('{path}', canvas.toBuffer('image/jpeg') 把数据以图片的方式推送给客户端,图片本身的算法帮助我们压缩了数据,不用自己捣鼓。事实上压缩率非常可观,前期画板上几乎都是重复颜色时,1.5M 数据甚至可以压缩到小于 10k,后期估计应该也在 300k 以内。

鉴于 DataURL 更方便,这里我采用的 DataURL 的方式传递图片数据。

工作记录

Day 1 把像素画板前端内容重构一遍,解决图像过大时放大视图卡顿的问题

Day 2 处理后端逻辑,由于数据库IO限制,尝试不同的存储结构,但性能都不理想

Day 3 继续问题研究,最后决定在服务端也同步一份 canvas 操作,而不是只存在库里,但流程还没走通,因为下午睡了一觉

Day 4 1核1G服务器在访问数据库取50w条数据时崩溃,后通过和朋友讨论,在无意中发现了实际问题,就有了解决方案(部分时间在新服务器配了套环境,不过由于问题解决又弃用了)

Day 5 增加公告、用户、聊天、像素点历史信息查询功能

Day 6/7 解决 socket.io https 问题,通宵两天最后发现是 CDN 加速问题,差点螺旋升天

Day 4 说的实际问题,我只能大概定位在 NodeJS 变量大小限制或对象个数限制,因为在我将 50w 长度 Array[Object] 转换为 200w 长度 Array[Number] 后问题消失了,知道具体原因的大佬望不吝赐教。

记录是从日记里复制过来的,Day 6/7 确实是最艰难的两天,其实代码从一开始就没什么错,有问题的是又拍云的 CDN 加速,可怖的是我根本没想到罪魁祸首是他。其实在两天的重复测试中,因为实在是无计可施,我也有两次怀疑 CDN 。第一次,我把域名解析到服务器 IP ,但测试结果仍然报错,之后就又恢复了加速。第二次是在第七天的早上五点,当时头很胀很难受就直接停了 CDN ,想着最后测试一下不行就去掉 CDN 的 https 证书用 http 访问。那时我才发现,在我 ping 域名确定解析已经改变后(修改解析后大概 10 分钟),域名又会间隙性被重新解析到 CDN (这个反复原因不知道为什么,阿里云的域名解析服务),第一次测试不准应该就是这个原因,稍长时间后就不再会了。解决后我有意恢复 CDN 加速测试,但始终没找出究竟是哪一个配置导致了问题,所以最终我也没能恢复加速。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/de9d4270f1c72cd66eebf08decae017a.html