将Rails应用程序中不明时间减少,并将速度提升了10倍的故事

你好。我是@srockstyle。

Ruby On Rails真是方便啊。作为一个框架,一直以来都有很多“像Rails一样方便!”的框架不断涌现。

这次是关于如何提升使用Rails开发的应用程序速度的故事。尽管如此,由于这是在大约2015年进行的工作,所以在现代环境中可能不适用。

这篇文章的结论最终是“现金好”。关于最近的现金趋势话题,我会另外写一篇。

事情的起源 (shì de qǐ

那时的我独自一人编写应用程序。

在作业接近尾声,解决了几乎所有的错误之后,我注意到了一个特定的现象。

スクリーンショット 2015-04-18 14.17.13.png

顺便说一下,这是一个远程服务器。数据库连接部分使用了缓存,所以速度还可以,云端也进行了一些设置,一切都还不错,但是还是有点慢。视图是9毫秒,活动记录是17毫秒,但整体花费了1570毫秒。
在Chrome上测量结果显示全部内容加载需要2.23秒。

其他网站。

我只是隨意挑選了一些看起來很重的網站,發現某個大型電子商務網站的響應時間為160毫秒,某個大型電子商務購物中心的響應時間為88毫秒。相比之下,我手機上的應用程序全部返回的時間卻需要2秒。太慢了。

探索1500毫秒的神秘本质

首先,我怀疑服务器的中间件。配置是nginx + Passenger V5(当时V5是最新的!)

由于设置没有问题,所以我现在查看了一下应该积累了缓存的memcache。

<35 GET ********(伏せてます)
<35 Read binary protocol data:
>35 Writing bin response:

这条日志表明缓存未生效。换句话说,原本应该被缓存的地方未被正确缓存。

Active Record 0.0ms之路

由于我从未发出写入查询,所以我试图将读取查询设置为零。由于财务原因,该应用程序无法创建副本。现在看来,这也是个原因。将写入用数据库和读取用数据库分开是基本的做法。

由於金錢問題無法解決,我先試著解決閱讀的問題吧。這是一個徹底的省錢方法。

缓存存储采用了memcached加Dalli。那时这是一种流行趋势。

    Dalli / github

在编写Active Record时,将修正处理步骤。

Rails.cache.fetch("key"){
    Model.where(flg: true).order("created_at DESC")
}

这是个错误的例子。

这是一个将ActiveRecord在执行SQL之前插入内容的行为。

于是我这样做了。

ret = Rails.cache.read(key)
if ret.nil?
    ret = Model.where(flg: true).order("created_at DESC").to_a
    Rails.cache.write(key,ret)
end

太冗长了。

一般而言,在fetch的AR后面添加to_a就可以了。

暫時,通過將其修改為這個方法來調用多個ActiveRecord將被緩存。原來必須將其正確轉換為數組。

寻找、通过查找

虽然这样说,但Rails的ActiveRecord不止有一个功能。还有find和find_by等。

这些问题已经得到了解决。

ret = Model.find(id).attributes.symbolize_keys

将属性设置为符号之后,您可以在哈希中进行访问。由于attribute时只能通过hash [ “”]访问,所以我有意地将其转换为符号。

如果有人知道好的方法,请告诉我……

通过缓存这个对象,find的问题就解决了。

关系

使用Rails时,会有以下类似的需求。

user = User.find(1)
pages = user.pages

如果在上面进行attributes并缓存,那么它只是一个简单的哈希,因此这没有意义关于关系。(Translated to Chinese)

在这里,我们使用缓存并将其加载到数组中来解决这个问题。

ret = Rails.cache.read(key)
if ret.nil?
    model = Model.where(flg: true).order("created_at DESC").to_a
  ret = model.pages.to_a
    Rails.cache.write(key,ret)
end

这里也是经过犹豫后决定成这个形式的,如果有什么好的方法,请告诉我。

通过这三项措施,Active Record现在可以在0.0毫秒内返回结果。

提高观看端的渲染速度

那么接下来就是视图方面了。在视图的渲染中往往会耗费300毫秒以上的时间,因此我希望尽量避免在这方面使用Rails的延迟处理。

我在这里使用了片段缓存。

关于片段缓存系统,以下提供了详细信息。

    Rails のフラグメントキャッシュで使われるキーについて

我参考了这个网站进行设置。因为有很多地方都是重复使用了部分模板,所以我将它们嵌入进去了。使用方法是这样的。

- cache obj do
 ## haml

haml很好,因为不需要后面绑定。通过将对象放入obj中来在循环中更改键。

经过全面的执行,我们可以看到相当大的改善。

结果

スクリーンショット 2015-04-18 14.46.49.png

首页响应速度减少至156毫秒!太棒了!

即使在Chrome开发者工具中观察,也仍然保持在大约300毫秒左右。

因為我覺得可能可以做得更快,所以我目前正在不斷嘗試和錯誤。如果有人知道什麼好方法的話,請一定留下評論,我將非常高興!

卡住了

写代码的方法 (xiě mǎ de

由于当时没有人对代码进行审查,我一个人写了上面的代码,所以无法确定它是否正确。
如果要做类似的事情,我认为还有更好的方法。

批量修改视图文件

应该会有更好的方法来处理这个问题,因为现在所有的代码都已经被改成了hash[:key]或者hash[“key”]的形式。

关系缓存

由于类似Rails特有的obj.store.name的写法失效了,让我感到很困扰。我尝试使用了一些能够顺利解决问题的Gem,但是变得非常复杂,所以我选择放弃了。
如果之后进行了调查,我会随时补充的。

整理

最开始我们怀疑是中间件调整或网络问题,但是根据日志显示的毫秒数最终发现这是应用程序返回时的日志,所以需要在应用程序端进行修正。

如果这个文件能对某人有所帮助,那就非常幸运了。

广告
将在 10 秒后关闭
bannerAds