MaaBackendCenter icon indicating copy to clipboard operation
MaaBackendCenter copied to clipboard

性能问题:应用启动或运行过程中出现OOM

Open dragove opened this issue 1 year ago • 12 comments

Copilot Query 接口在 qps 稍大时或者 limit 稍大时在小服务器上运行压力较大,容易OOM -- 沃夏. 边德

优化可能性:

  • [x] 添加首页数据缓存,即默认不带任何查询参数时根据热度排序的结果,由于数据更新频率为每天,因此可以考虑
  • [x] 接口入参 limit 添加限制为50上限,过大limit容易导致OOM
  • [ ] #124
  • [x] 考虑优化 rating 数据的存储方式?(暂时没想法怎么改,目前存RatingUsers列表,在query接口读取数据时总共内存占用可能较多) https://github.com/MaaAssistantArknights/MaaBackendCenter/pull/128
  • [ ] 考虑迁移数据到mysql(mariadb)?

dragove avatar Aug 16 '23 17:08 dragove

本项目没有部署性能监控和链路跟踪吗?性能问题纯靠猜很难定位真正的问题啊。

Lixuhuilll avatar Aug 17 '23 03:08 Lixuhuilll

本项目没有部署性能监控和链路跟踪吗?性能问题纯靠猜很难定位真正的问题啊。

2G内存的服务器再塞这些有点过分了。分析过OOM时的dump数据。占用大量内存的主要对象的类型为 MongoBatchCursorAdapter 和 ArrayList

通过nginx access_log可以发现访问量最多的接口为 query 接口,qps 最高有30多,通过nginx切断请求后启动应用再恢复也恢复了正常。

恢复正常后通过修改前端请求的limit再次导致了OOM

dragove avatar Aug 17 '23 04:08 dragove

如果是这样的话,加缓存和限制 limit 这些手段确实简单有效。

Lixuhuilll avatar Aug 17 '23 05:08 Lixuhuilll

a4e54af3b95cb794f3ae60dfedf629c1 关联前端的一点性能优化想法:

  1. 目前触发的查询都是两次的,可能在实现上存在缺陷。
  2. 目前在搜索栏输入内容就会触发查询,连续输入就会触发高频的查询,是否考虑增加一个输入抗抖动,例如在停止输入500ms以后再发起查询?

BTreeNewBee avatar Aug 17 '23 13:08 BTreeNewBee

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

Lixuhuilll avatar Aug 19 '23 14:08 Lixuhuilll

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

我觉得挺好的 我想到的也是这个

LuoRenMu avatar Aug 20 '23 09:08 LuoRenMu

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

我觉得挺好的 我想到的也是这个

我目前已经写的差不多了,正在做旧数据迁移的代码编写,等我散完步回来再做一下测试,然后就发个PR看看。

Lixuhuilll avatar Aug 20 '23 11:08 Lixuhuilll

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

我觉得挺好的 我想到的也是这个

你认为是运行的时候,读到旧数据就迁移,还是搞一个定时任务统一迁移?定时任务统一迁移在完全迁移前还是得照顾旧数据,要做识别,我目前的代码是碰到旧数据就迁移,然后逻辑差不多,所以就复制粘贴了好几个,确认迁移完了以后只要把这些代码都移除就行。

Lixuhuilll avatar Aug 20 '23 11:08 Lixuhuilll

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

我觉得挺好的 我想到的也是这个

你认为是运行的时候,读到旧数据就迁移,还是搞一个定时任务统一迁移?定时任务统一迁移在完全迁移前还是得照顾旧数据,要做识别,我目前的代码是碰到旧数据就迁移,然后逻辑差不多,所以就复制粘贴了好几个,确认迁移完了以后只要把这些代码都移除就行。

热门数据的ratingUser里应该至少上百了吧 查询的时候迁移不知道会不会造成阻塞?

LuoRenMu avatar Aug 20 '23 12:08 LuoRenMu

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

我觉得挺好的 我想到的也是这个

你认为是运行的时候,读到旧数据就迁移,还是搞一个定时任务统一迁移?定时任务统一迁移在完全迁移前还是得照顾旧数据,要做识别,我目前的代码是碰到旧数据就迁移,然后逻辑差不多,所以就复制粘贴了好几个,确认迁移完了以后只要把这些代码都移除就行。

热门数据的ratingUser里应该至少上百了吧 查询的时候迁移不知道会不会造成阻塞?

这倒是不会,因为原先的旧数据在每次查询的时候都会便利一下找到自己是否有出现在ratingUser中,迁移数据的时空复杂度和这一个操作基本是同一个量级。

Lixuhuilll avatar Aug 20 '23 12:08 Lixuhuilll

这样优化会不会更合理: RatingUser列表不直接保存,一个 rating 信息只保留点赞数、点踩数。然后另起一个document,通过复合唯一索引,将作业id和userid联合,通过这个复合索引快速查找ratingtype和ratingtime。 这样就可以快速获取点赞数和获知当前用户是否点赞该作业。

我觉得挺好的 我想到的也是这个

你认为是运行的时候,读到旧数据就迁移,还是搞一个定时任务统一迁移?定时任务统一迁移在完全迁移前还是得照顾旧数据,要做识别,我目前的代码是碰到旧数据就迁移,然后逻辑差不多,所以就复制粘贴了好几个,确认迁移完了以后只要把这些代码都移除就行。

热门数据的ratingUser里应该至少上百了吧 查询的时候迁移不知道会不会造成阻塞?

这倒是不会,因为原先的旧数据在每次查询的时候都会便利一下找到自己是否有出现在ratingUser中,迁移数据的时空复杂度和这一个操作基本是同一个量级。

也是

LuoRenMu avatar Aug 20 '23 12:08 LuoRenMu

私以为,以目前首页每次查询都会遍历50个数组的情况,能坚持到近一段时间才出现oom,已经够离谱的了。

Lixuhuilll avatar Aug 20 '23 12:08 Lixuhuilll