Forum 论坛项目 极致[性能优化]总结分享
对于webman/或者常驻内存的的cli程序,都有一定的相互参考借鉴的价值。
我的站点是 GooseForum
源码: github.com/leancodebox/GooseForum
最快的 web 应该是在做什么
获取到请求,直接从内存中获取数据,然后返回最简短的结果。
一个web的生命周期带着什么
路由,逻辑/运行,查询/io, 压缩,传输
我们应该朝着最快的web的方向做整体的优化,同时还要保证优化后的请求和优化前的用户感受在一定范围是幂等。
优化方向也是拿空间换时间,和拿时间换空间两者结合的处理,以高速查询替代低速查询。
这里列出GooseForum所有的关于性能的优化项目
1、前端静态资源Gzip压缩,并且所有Gzip的资源都加载到内存中。
这歌个场景是空间换时间和时间换空间的相互配合的结果,
首先是开启Gzip后,返回的前端资源会减少80%以上的大小。这很利于利用有效的带宽在未来为更多的人提供服务
其次是GooseForum本身的前端资源是通过golang embed 嵌入到项目之中的,所以把所有文件Gzip后存到内存中数量也是非常有限的,所以不用担心oom(内存泄露)的发生,并且Gzip本身还是会消耗不少的cpu甚至大于许多接口页面本身的逻辑,所以这里是非常值得这样优化的。
2、哈希+浏览器缓存
对于前端非页面内容的资源,例如图片/css/jss等一系列静态资源,我们可以利用浏览器特性,不要每次都发起网络请求,浏览器缓存后即可,这一块可以减少很大的带宽。我们只需要处理好这些静态资源的哈希即刻,即不要让不同文件的静态资源保持相同名字,这里我是用的vite打包,所以不用担心这个。
3、内存缓存/数据冗余
这里也是GooseForum开发过程中需要优化的点,因为这里需要进行数据量级的判断,缓存时间的判断,时效性的判断。
例如站点的 页面上的分类/首页的推荐 因为是高访问,低更新,所以存储在内存变量中,通过时间判断是否过期,因为这块数据数据量极其小并且有限,所以我们不用手动处理过期删除,只需要在请求的时候发现过期重新生成一下即可。
数据冗余这一点也很重要,因为复杂的设计必然会产生许多关联表以达到关系清晰便于维护的目的(复杂的关系,如果偷懒不拆关系表,后面会导致许多功能迭代的受限),同时冗余也是为了减少计算。
这里有两块内容,
文章的分类,因为 GooseForum 是支持用户多分类选择查询的,所以设计有关系表,但是除了列表以外的其他地方并不需要查询列表,只要文章的主题类别,那么冗余就很有必要的了。
文章markdown转化html渲染其实是很耗费资源的,这里会在用户发布之后将 转化后的 content html 存储下来,这样就极大降低了服务端的渲染压力,同时我们还可以把一些难以渲染的数据让客户端进行渲染,例如 GooseForum 只渲染 commonmark,至于 mermaid 之类的流程图,是让前端去处理的。这是一个balance的方案。
4、热数据/更新频率/查询频率
1 项目中登陆的用户数据会视为热数据,放到 bigCache 中缓存一分钟,如果用户发发生了数据更新会重新更新这个cache,这样可以极大减少重复数据的获取。
2 项目中每个作者的热点文章也是不同的,这里采用类似 user 缓存的策略,但是这里不会去主动reload最新数据,因为这里的实效性是低于user的(毕竟用户更新了数据,但是发现右上角头像没变会让人当成bug),所以等待自然过期,然后再加载到缓存中
3 GooseForum 的消息通知采用的是js发起轮询的方式,那么就要考虑如果用户打开多个浏览器tab的情况下,发起大量重复的请求的情况,这里是参考了之前 Learnku 站长的优化方案,采用 localstorage 进行数据缓存,如果发现多长时间内已经有请求过的历史,就不在请求了,这样就防止打开多个页面的时候所有页面都在请求查询的问题。
4 异步合并写入,这里GooseForum有两个地方用到了该技术,
1是日志的写入,有专门的异步处理,这样即使是日志增多也不会被io阻塞主逻辑,
2是用户活跃时间,这里采用了异步收集,集中写入的方案,异步放到同一个map之中,定时查一下这个map中是否有需要刷入db的数据,对于同一个活跃用户,如果最后的活跃时间不停的更新就会更新最后的活跃时间,不会立刻写入,同时还有一个附加逻辑,就是如果这个异步任务创建了已经超过了45s但是还没有写入,就会强行写入,否则判断活跃时间是否超过15s 即可,这样会极大减少用户写入的频率。
综上,都是在做一些平衡优化,用最小的带宽在最快的io和最少的cpu运算下,以一定范围幂等,或者某些场景下完全幂等的,以可控的内存空间换得一个理想的响应速度。
对于 php-cli 的一些项目使用 apcu 和 内存变量缓存也可以达到类似的效果。
如果其他同学有其他想法和方案也可以分享一下
本作品采用《CC 协议》,转载必须注明作者和本文链接