Ruby on Rails
Buforowanie
Szukaj…
Buforowanie rosyjskich lalek
Możesz zagnieździć buforowane fragmenty w innych buforowanych fragmentach. Nazywa się to Russian doll caching
.
Zaletą Russian doll caching
jest to, że jeśli pojedynczy produkt zostanie zaktualizowany, wszystkie pozostałe fragmenty wewnętrzne można ponownie wykorzystać podczas regeneracji fragmentu zewnętrznego.
Jak wyjaśniono w poprzedniej sekcji, buforowany plik wygaśnie, jeśli wartość updated_at
zmieni się dla rekordu, od którego bezpośrednio zależy buforowany plik. Jednak nie wygasa żadna pamięć podręczna, w której zagnieżdżony jest fragment.
Weźmy na przykład następujący widok:
<% cache product do %>
<%= render product.games %>
<% end %>
Co z kolei renderuje ten widok:
<% cache game do %>
<%= render game %>
<% end %>
Jeśli jakikolwiek atrybut gry zostanie zmieniony, wartość updated_at
zostanie ustawiona na bieżący czas, tym samym wygasając pamięć podręczną.
Ponieważ jednak parametr updated_at
nie zostanie zmieniony dla obiektu produktu, pamięć podręczna nie wygasa, a aplikacja będzie obsługiwać nieaktualne dane. Aby to naprawić, łączymy modele razem z metodą dotykową:
class Product < ApplicationRecord
has_many :games
end
class Game < ApplicationRecord
belongs_to :product, touch: true
end
Buforowanie SQL
Buforowanie zapytań to funkcja Rails
która buforuje zestaw wyników zwracany przez każde zapytanie. Jeśli Rails
napotka ponownie to samo zapytanie dla tego żądania, użyje buforowanego zestawu wyników, a nie ponownie uruchomi zapytanie w bazie danych.
Na przykład:
class ProductsController < ApplicationController
def index
# Run a find query
@products = Product.all
...
# Run the same query again
@products = Product.all
end
end
Za drugim razem, gdy to samo zapytanie zostanie uruchomione w bazie danych, tak naprawdę nie trafi do bazy danych. Za pierwszym razem, gdy wynik jest zwracany z zapytania, jest on przechowywany w pamięci podręcznej zapytania (w pamięci), a za drugim razem jest pobierany z pamięci.
Należy jednak pamiętać, że pamięci podręczne zapytań są tworzone na początku akcji i niszczone na końcu tej akcji, a zatem są przechowywane tylko przez czas trwania akcji. Jeśli chcesz przechowywać wyniki zapytania w bardziej trwały sposób, możesz to zrobić z buforowaniem niskiego poziomu.
Buforowanie fragmentów
Rails.cache
, dostarczany przez ActiveSupport, może być użyty do buforowania każdego możliwego do serializacji obiektu Ruby między żądaniami.
Aby pobrać wartość z pamięci podręcznej dla danego klucza, użyj cache.read
:
Rails.cache.read('city')
# => nil
Użyj cache.write
aby zapisać wartość w pamięci podręcznej:
Rails.cache.write('city', 'Duckburgh')
Rails.cache.read('city')
# => 'Duckburgh'
cache.fetch
użyć cache.fetch
aby odczytać wartość z bufora i opcjonalnie napisać wartość domyślną, jeśli nie ma wartości:
Rails.cache.fetch('user') do
User.where(:is_awesome => true)
end
Zwracana wartość przekazywanego bloku zostanie przypisana do pamięci podręcznej pod danym kluczem, a następnie zwrócona.
Możesz także określić datę ważności pamięci podręcznej:
Rails.cache.fetch('user', :expires_in => 30.minutes) do
User.where(:is_awesome => true)
end
Buforowanie strony
Możesz użyć klejnotu ActionPack page_caching do buforowania poszczególnych stron. Przechowuje wynik jednego żądania dynamicznego jako statyczny plik HTML, który jest wyświetlany zamiast żądania dynamicznego przy kolejnych żądaniach. Plik README zawiera pełne instrukcje konfiguracji. Po skonfigurowaniu użyj metody klasy caches_page
w kontrolerze, aby buforować wynik działania:
class UsersController < ActionController::Base
caches_page :index
end
Użyj expire_page
aby wymusić wygaśnięcie pamięci podręcznej poprzez usunięcie zapisanego pliku HTML:
class UsersController < ActionController::Base
caches_page :index
def index
@users = User.all
end
def create
expire_page :action => :index
end
end
Składnia expire_page
naśladuje składnię url_for
i znajomych.
Buforowanie HTTP
Railsy> = 3 są dostarczane z funkcjami buforowania HTTP po wyjęciu z pudełka. Wykorzystuje to nagłówki Cache-Control
i ETag
do kontrolowania, jak długo klient lub pośrednik (np. CDN) może buforować stronę.
W akcji kontrolera użyj expires_in
aby ustawić długość buforowania dla tej akcji:
def show
@user = User.find params[:id]
expires_in 30.minutes, :public => true
end
Użyj expires_now
aby wymusić natychmiastowe wygaśnięcie buforowanego zasobu na każdym odwiedzającym kliencie lub pośredniku:
def show
@users = User.find params[:id]
expires_now if params[:id] == 1
end
Buforowanie akcji
Podobnie jak buforowanie stron, buforowanie akcji buforuje całą stronę. Różnica polega na tym, że żądanie trafia w stos Railsów, więc przed uruchomieniem filtrów przed podaniem pamięci podręcznej. Jest wyodrębniany z Railsa do klejnotu actionpack-action_caching .
Typowym przykładem jest buforowanie akcji wymagającej uwierzytelnienia:
class SecretIngredientsController < ApplicationController
before_action :authenticate_user!, only: :index, :show
caches_action :index
def index
@secret_ingredients = Recipe.find(params[:recipe_id]).secret_ingredients
end
end
Dostępne opcje to :expires_in
, niestandardowy :cache_path
(dla akcji z wieloma trasami, które powinny być buforowane w inny sposób) oraz :if
/ :unless
że kontroluje, kiedy akcja powinna być buforowana.
class RecipesController < ApplicationController
before_action :authenticate_user!, except: :show
caches_page :show
caches_action :archive, expires_in: 1.day
caches_action :index, unless: { request.format.json? }
end
Gdy układ ma treść dynamiczną, buforuj tylko treść akcji, przekazując layout: false
.