Ruby on Rails接口性能优化实践

存在的问题

最近一段时间在做性能优化的工作,项目是Rails单体,使用的RESTful APIMongoDB数据库,按照二八定律,先用20%的精力去达到80%的效果,主要是优化了首页相关接口,之前N+1查询相关问题已经解决,通过对ELK APM性能监控分析发现,影响列表接口性能的地方,主要集中在3个方面:

  • 查询当前用户加入资源的数量
  • 查询当前用户是否加入列表的资源
  • 无用数据返回过多

针对存在的问题,采取了下面的解决方案。

解决方案

查询当前用户加入资源的数量

  • 之前项目数据量比较小,对于用户相关的数量进行实时查询,随着数据和用户量的增加,访问速度变慢需要进行重构,Rails提供的counter_cache的方法已经不太够用。这部分的优化参考了Ruby China homeland的做法,主要的思路是将数量相关的数据进行持久化,不再单个进行查询,创建一个Counter类,存储数量相关的数据,主要代码实现如下:
class Counter < ApplicationRecord
  belongs_to :countable, polymorphic: true
  ...
end

具体实现可参考Ruby China homeland项目

查询当前用户是否加入列表的资源

  • 目前采取的方式是借助Ruby on Rails ActiveSupport::CurrentAttributes,它提供了线程隔离属性单例,可以在每个请求,将当前用户传到系统中直接进行查询。
  • 之前同事专门写了一个gem mongoid-association_scope,将Active Support::CurrentAttributes应用到mongoid当中,目前仅支持到mongoid 6,后面有时间和精力支持到mongoid最新版本。
  • 以课程为例,判断当前登录用户加入哪些列表的资源,参考代码如下:
class Course
  has_one :current_member, -> { Current.user ? where(user: Current.user) : none }, class_name: "CourseUser", inverse_of: :course
 end

ActiveSupport::CurrentAttributes使用注意事项:
A word of caution: It’s easy to overdo a global singleton like Current and tangle your model as a result. Current should only be used for a few, top-level globals, like account, user, and request details. The attributes stuck in Current should be used by more or less all actions on all requests. If you start sticking controller-specific attributes in there, you’re going to create a mess.
关键点是不过过度使用,主要使用在顶级全局变量,如账户、用户和请求详细信息等。

无用数据返回过多

  • 使用grape entity定义接口返回的数据,项目体量小时为快速开发,列表和详情的entities会使用同一个,随着功能增多,详情接口需要的数据会变多,又未将列表与详情中数据分开,导致列表接口返回的数据也变多了,时间久了会出现性能问题。
  • 当列表接口变慢时,需要进行重构和优化,通过查看ELK APM性能检测,哪些字段影响了性能,再与前端进行沟通确认,将不需要的字段进行删除,这时需要考虑版本兼容的问题。
  • 这部分的难点主要在于,如何将这部分工作融入日常的开发迭代中,在每个迭代周期需要加入相关的任务,这部分的工作在开发阶段体现不出价值,但从软件整个生命周期来看,能够大大降低项目的维护成本。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值