如何缓存rails api控制器
Posted
技术标签:
【中文标题】如何缓存rails api控制器【英文标题】:How to cache a rails api controller 【发布时间】:2020-09-10 05:44:16 【问题描述】:我在我的应用程序中发现了一些性能问题,我想知道我的缓存是否工作正常,或者我是否误解/错误配置了任何内容。我使用fast-jsonapi 进行序列化,它带有内置缓存选项。
假设:
class BooksController < ApplicationController
...
def index
@books = Books.includes(:author, :publisher).with_attached_cover.all
BookSerializer.new(@book, include: [:author, :publisher]).serializable_hash.to_json
end
...
end
和
class BookSerializer
include FastJsonapi::ObjectSerializer
cache_options store: Rails.cache, namespace: 'fast-jsonapi', expires_in: 24.hours
belongs_to :author
belongs_to :publisher
attributes :all_the_book_attributes_im_too_lazy_to_list
end
还假设我有大约 5000 本书,有 2000 位作者和 100 位出版商,所以我希望缓存会对性能产生很大影响。
但是,事实上,无论是否启用缓存,我都看到我的数据库以相同的方式命中,而且响应时间确实很慢。此外,在检查我的缓存时,它似乎只缓存了每一本书,而不是整个序列化的哈希。
现在我想知道我是否完全错过了在序列化程序中缓存的目的,或者我是否需要在控制器中添加一些额外的层?如果是,是否有解决方案以 DRY 方式执行此操作?会不会和序列化器的缓存冲突?那么,序列化程序中缓存的目的是什么?
我知道我可以使用多种方式/缓存层。我只是不确定要合并哪些以及是否要防止这些层之间的任何冲突。
【问题讨论】:
你是在开发模式还是生产模式下尝试这个? 【参考方案1】:我可以看到你想要缓存这个 JSON 响应。
为此查询添加缓存键。当书籍随时间发生变化时,您需要使用它来使响应无效。
# model book.rb
class Book < ApplicationRecord
...
def self.cache_key
serializer: 'books',
stat_record: Book.maximum(:updated_at)
end
...
end
在您的控制器中使用该键从缓存中获取数据或进行新查询:
class BooksController < ApplicationController
...
def index
@books = Rails.cache.fetch(Book.cache_key) do
BookSerializer.new(
Books.includes(:author, :publisher).with_attached_cover.all,
include: [:author, :publisher]
).serializable_hash.to_json
end
render json: @books
end
...
end
您还可以查看页面缓存。
顺便说一句,如果你有 5000 个条目,你应该考虑分页。
【讨论】:
以上是关于如何缓存rails api控制器的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Devise 和 JWT 与我的版本化 API Rails 控制器一起工作?