我在Heroku上运行了一个生产Rails应用程序,并且一些API端点需要很长时间才能解决(~1-2s)。
这是一个正常的Rails RESTful GET操作cases#index
。方法如下:
@cases = cases_query
meta = {
total: @cases.total_count,
count: params[:count],
page: params[:page],
sort: params[:order],
filter: pagination[:filter],
params: params
}
render json: @cases,
root: 'cases',
each_serializer: CaseSerializer,
meta: meta
该方法运行ActiveRecord查询以选择数据,序列化每个记录并呈现JSON。 Skylight,一个Rails分析器/监视/性能工具,告诉我这个端点在控制器方法(在Ruby中)占70%,在数据库中占30%。
此代码或我的应用设置中的内容是什么导致这在应用代码中花费了这么多时间?它可能是一颗宝石吗?
此端点上的Skylight分析图片(您可以在控制器操作中看到Ruby花费的大部分时间):
答案 0 :(得分:1)
ActiveRecord可以从查询中生成大量的Ruby对象。因此,您可以跟踪数据库返回结果所需的时间,这可能是您请求的大约20%,但其余的仍然可以在ActiveRecord中将这些结果转换为Ruby对象。
您对此请求的查询是否会返回大量行?这些行是否非常宽(例如当你连接table1。,table2。,table3。*)时?
我在过去有过一些经验,其中序列化程序确实非常破坏性能。这通常最终会逐条寻找负责任的人。
要解决此问题,我建议您找一种方法来获得有关性能的实时或接近实时的反馈。 newrelic_rpm gem有一个/newrelic
页面,你可以在开发模式下查看,它应该提供类似于Skylight的反馈。天窗可能有一个类似你应该研究的开发模式页面。
还有一个名为Peek的宝石,它为每个页面视图添加了一个性能指标,您可以添加宝石以显示请求的特定切片,如DB,视图甚至垃圾收集。 https://github.com/peek/peek检查一下,特别是GC插件。
一旦有了实时反馈设置,并且您可以看到大致映射到天窗输出的内容,您就可以开始在代码中使用二进制搜索来隔离性能问题。
在您的控制器中,通过以下方式消除渲染步骤:
render json: {}
并查看该请求的结果。如果性能显着提高,那么您的问题可能就在序列化阶段。
如果没有,那么可能是ActiveRecord炸毁了Ruby对象空间。做谷歌搜索Ruby对象空间分析,你会找到解决这个问题的方法。
如果这是您的问题,请尝试缩小查询返回的结果范围。 select
仅显示您在此响应中需要呈现的列。尽可能尝试消除连接(通过返回外键而不是对象,如果可能的话)。
如果序列化是你的问题......祝你好运。根据我的经验,这个特别难以排除故障。您可以尝试使用更高效的JSON gem(如OJ
),或者使用硬编码序列化程序而不是使用ActiveRecord :: Serializer(最后的手段!)。
答案 1 :(得分:0)
通常情况下,数据库查询会导致此类问题重新访问数据库查询,并尽可能优化它们应用连接。
还尝试将Puma gem
与heroku一起使用,以提高服务器性能。