edge
Daugiau informacijos rubyonrails.org: Daugiau apie Ruby on Rails

Podėliavimas su Rails: Apžvalga

Šis vadovas yra įvadas į jūsų Rails aplikacijos pagreitinimą naudojant podėliavimą.

Podėliavimas reiškia saugoti turinį, kuris yra generuojamas per užklausos-atsakymo ciklą ir jį naudoti, kai atsakoma į panašias užklausas.

Podėliavimas dažnai yra efektyviausias būdas pagerinti aplikacijos veikimą. Naudojant podėliavimą, svetainės, veikiančios viename serveryje su viena duomenų baze, gali išlaikyti tūkstančius vienu metu prisijungusių vartotojų apkrovą.

Rails pateikia rinkinį podėliavimo funkcijų iš anksto. Šis vadovas jums parodys kiekvienos iš jų apimtį ir tikslą. Išmanydami šias technikas, jūsų Rails aplikacijos gali aptarnauti milijonus peržiūrų be per didelių atsakymo laikų ar serverio sąskaitų.

Po šio vadovo perskaitymo, jūs žinosite:

1 Pagrindinis podėliavimas

Tai yra įvadas į tris podėliavimo technikas: puslapio, veiksmo ir fragmento podėliavimą. Pagal numatytuosius nustatymus, Rails pateikia fragmento podėliavimą. Norėdami naudoti puslapio ir veiksmo podėliavimą, jums reikės pridėti actionpack-page_caching ir actionpack-action_caching į savo Gemfile.

Pagal numatytuosius nustatymus, podėliavimas yra įjungtas tik jūsų produkcinėje aplinkoje. Galite išbandyti podėliavimą vietiniame kompiuteryje paleisdami rails dev:cache arba nustatydami config.action_controller.perform_caching reikšmę į true config/environments/development.rb faile.

PASTABA: Pakeitus config.action_controller.perform_caching reikšmę, tai turės poveikį tik Action Controller teikiamam podėliavimui. Pavyzdžiui, tai neturės įtakos žemam lygio podėliavimui, kurį aptariame žemiau.

1.1 Puslapio podėliavimas

Puslapio podėliavimas yra Rails mechanizmas, leidžiantis užklausai, skirtai sugeneruotam puslapiui, būti patenkintai interneto serverio (pvz., Apache ar NGINX) be poreikio eiti per visą Rails paketą. Nors tai yra labai greita, tai negali būti taikoma visoms situacijoms (pvz., puslapiams, reikalaujantiems autentifikacijos). Taip pat, nes interneto serveris aptarnauja failą tiesiogiai iš failų sistemos, jums reikės įgyvendinti podėlio galiojimą.

INFORMACIJA: Puslapio podėliavimas buvo pašalintas iš Rails 4. Žr. actionpack-page_caching gemą.

1.2 Veiksmo podėliavimas

Puslapio podėliavimas negali būti naudojamas veiksmams, kuriuose yra prieš filtro - pavyzdžiui, puslapiams, reikalaujantiems autentifikacijos. Čia įsikiša Veiksmo podėliavimas. Veiksmo podėliavimas veikia kaip Puslapio podėliavimas, išskyrus tai, kad įeinanti interneto užklausa pasiekia Rails paketą, kad prieš filtrai galėtų būti vykdomi prieš podėlį aptarnaujant. Tai leidžia vykdyti autentifikaciją ir kitus apribojimus, tuo pačiu metu aptarnaujant rezultatą iš podėlio kopijos.

INFORMACIJA: Veiksmo podėliavimas buvo pašalintas iš Rails 4. Žr. actionpack-action_caching gemą. Žr. DHH raktinio podėlio galiojimo apžvalgą dėl naujo pageidaujamo metodo.

1.3 Fragmento podėliavimas

Dinaminės interneto aplikacijos paprastai kuria puslapius su įvairiais komponentais, kurių ne visi turi tokius pačius podėlio savybes. Kai skirtingi puslapio dalys turi būti podėliuojamos ir galiojamos atskirai, galite naudoti Fragmento podėliavimą.

Fragmento podėliavimas leidžia apgaubti dalį rodinio logikos podėlio bloku ir aptarnauti jį iš podėlio saugyklos, kai ateina kitas užklausos.

Pavyzdžiui, jei norėtumėte podėliuoti kiekvieną produktą puslapyje, galėtumėte naudoti šį kodą:

<% @products.each do |product| %>
  <% cache product do %>
    <%= render product %>
  <% end %>
<% end %>

Kai jūsų aplikacija gauna pirmą užklausą į šį puslapį, Rails įrašys naują podėlio įrašą su unikaliu raktu. Raktas atrodo kažkaip taip:

views/products/index:bea67108094918eeba42cd4a6e786901/products/1

Viduryje esantis simbolių eilutė yra šablono medžio skaitinė reikšmė. Tai yra maišos reikšmė, apskaičiuota pagal rodinio fragmento turinio, kurį jūs podėliuojate. Jei pakeisite rodinio fragmentą (pvz., HTML keičiasi), maišos reikšmė pasikeis, galiojant esamam failui.

Podėlio įraše saugoma podėlio versija, gauta iš produkto įrašo. Kai produktas yra paliestas, podėlio versija keičiasi, ir bet kokie podėliuoti fragmentai, kuriuose yra ankstesnė versija, yra ignoruojami.

PATARIMAS: Podėlio saugyklos, pvz., Memcached, automatiškai ištrins senus podėlio failus.

Jei norite podėliuoti fragmentą pagal tam tikras sąlygas, galite naudoti cache_if arba cache_unless:

<% cache_if admin?, product do %>
  <%= render product %>
<% end %>

1.3.1 Rinkinio podėliavimas

render pagalbininkas taip pat gali podėliuoti atskirus šablonus, kurie yra sugeneruojami rinkiniui. Jis netgi gali pagerinti ankstesnį pavyzdį su each, skaitant visus podėlio šablonus iš karto, o ne vieną po kito. Tai padaroma perduodant cached: true, kai renderinamas rinkinys: html+erb <%= render partial: 'products/product', collection: @products, cached: true %>

Visi iš anksto užregistruoti šablonai bus gauti vienu metu, kuris leis greičiau atvaizduoti puslapį. Be to, šablonai, kurie dar nėra užregistruoti, bus įrašyti į talpyklą ir bus gauti kartu su kitu atvaizdavimu.

1.4 Rusiško lėlių talpinimas

Galite norėti įdėti talpyklą į kitą talpyklą. Tai vadinama rusišku lėlių talpinimu.

Rusiško lėlių talpinimo privalumas yra tas, kad jei vienas produktas yra atnaujinamas, visi kiti vidiniai fragmentai gali būti pernaudojami, kai atnaujinamas išorinis fragmentas.

Kaip paaiškinta ankstesniame skyriuje, užregistruotas failas pasibaigs, jei updated_at reikšmė pasikeis tam tikram įrašui, nuo kurio priklauso užregistruotas failas. Tačiau tai nesibaigs jokios talpyklos, į kurią įterptas fragmentas.

Pavyzdžiui, turime šį rodinį:

<% cache product do %>
  <%= render product.games %>
<% end %>

Kuris savo ruožtu atvaizduoja šį rodinį:

<% cache game do %>
  <%= render game %>
<% end %>

Jei bet kuri game atributas pasikeis, updated_at reikšmė bus nustatyta į dabartinį laiką, taip pasibaigiant talpyklai. Tačiau, nes updated_at nebus pakeistas produktų objekte, talpykla nesibaigs ir jūsų programa bus naudojama pasenusi informacija. Norint tai ištaisyti, susieję modelius sujungiame su touch metodu:

class Product < ApplicationRecord
  has_many :games
end

class Game < ApplicationRecord
  belongs_to :product, touch: true
end

Nustatę touch į true, bet kokia veikla, kuri pakeičia updated_at žaidimo įrašui, taip pat pakeis jį susijusiam produktui, taip pasibaigiant talpyklai.

1.5 Bendrinė dalinio talpinimas

Įmanoma dalintis daliniais ir susijusia talpykla tarp failų su skirtingais MIME tipais. Pavyzdžiui, bendrinis dalinio talpinimas leidžia šablonų kūrėjams dalintis daliniu tarp HTML ir JavaScript failų. Kai šablonai yra surinkti šablonų išieškotojo failų keliuose, jie apima tik šablono kalbos plėtinį, o ne MIME tipą. Dėl šios priežasties šablonai gali būti naudojami keliose MIME tipose. Abi HTML ir JavaScript užklausos atsakys į šį kodą:

render(partial: 'hotels/hotel', collection: @hotels, cached: true)

Bus įkeltas failas pavadinimu hotels/hotel.erb.

Kitas variantas yra įtraukti visą dalinio failo pavadinimą, kurį norite atvaizduoti.

render(partial: 'hotels/hotel.html.erb', collection: @hotels, cached: true)

Bus įkeltas failas pavadinimu hotels/hotel.html.erb bet kuriame failo MIME type, pavyzdžiui, galėtumėte įtraukti šį dalinį į JavaScript failą.

1.6 Priklausomybių valdymas

Norėdami teisingai atšaukti talpyklą, turite tinkamai apibrėžti talpyklos priklausomybes. „Rails“ yra pakankamai protingas, kad galėtų tvarkyti dažnai pasitaikančius atvejus, todėl jums nereikia nieko nurodyti. Tačiau kartais, pvz., jei dirbate su tinkintais pagalbininkais, turite aiškiai juos apibrėžti.

1.6.1 Neaiškios priklausomybės

Dauguma šablonų priklausomybių gali būti išvestos iš „render“ iškvietimų šablone. Štai keli „ActionView::Digestor“ žino, kaip dekoduoti pavyzdžiai:

render partial: "comments/comment", collection: commentable.comments
render "comments/comments"
render 'comments/comments'
render('comments/comments')

render "header" verčia render("comments/header")

render(@topic)         verčia render("topics/topic")
render(topics)         verčia render("topics/topic")
render(message.topics) verčia render("topics/topic")

Kita vertus, kai kurie iškvietimai turi būti pakeisti, kad talpykla tinkamai veiktų. Pavyzdžiui, jei perduodate tinkintą kolekciją, turėsite pakeisti:

render @project.documents.where(published: true)

į:

render partial: "documents/document", collection: @project.documents.where(published: true)

1.6.2 Aiškios priklausomybės

Kartais turėsite šablonų priklausomybes, kurios visiškai negali būti išvestos. Tai paprastai yra atvejis, kai atvaizduojama pagalba. Štai pavyzdys:

<%= render_sortable_todolists @project.todolists %>

Turėsite naudoti specialų komentaro formatą, kad tai pažymėtumėte:

<%# Šablono priklausomybė: todolists/todolist %>
<%= render_sortable_todolists @project.todolists %>

Kai kuriais atvejais, pvz., naudojant vieno lentelės paveldėjimo sąranką, galite turėti daug aiškių priklausomybių. Vietoje kiekvieno šablono rašymo galite naudoti ženklą, kad atitiktų bet kurį šablono kataloge:

<%# Šablono priklausomybė: events/* %>
<%= render_categorizable_events @person.events %>

Dėl kolekcijos talpinimo, jei dalinio šablonas neprasideda švariu talpyklos iškvietimu, vis tiek galite naudotis kolekcijos talpinimu pridedami specialų komentaro formatą bet kurioje šablone, pvz.:

<%# Šablono kolekcija: notification %>
<% my_helper_that_calls_cache(some_arg, notification) do %>
  <%= notification.name %>
<% end %>

1.6.3 Išorinės priklausomybės

Jei naudojate pagalbinį metodą, pavyzdžiui, viduje talpyklos bloko, ir tada atnaujinote tą pagalbinį metodą, taip pat turėsite atnaujinti talpyklą. Nėra svarbu, kaip tai padarysite, bet šablonų failo MD5 turi pasikeisti. Vienas rekomenduojamas būdas yra tiesiog būti aiškus komentare, pavyzdžiui:

<%# Pagalbinės priklausomybės atnaujintos: 2015 m. liepos 28 d., 19 val. %>
<%= some_helper_method(person) %>

1.7 Žemo lygio talpinimas

Kartais jums reikia talpinti tam tikrą reikšmę ar užklausos rezultatą, o ne talpinti rodinio fragmentus. „Rails“ talpinimo mechanizmas puikiai tinka saugoti bet kokius serijinius duomenis.

Efektyviausias būdas įgyvendinti žemo lygio talpinimą yra naudojant Rails.cache.fetch metodą. Šis metodas atlieka tiek skaitymą, tiek rašymą į talpyklą. Jei perduodamas tik vienas argumentas, gaunamas raktas ir grąžinama reikšmė iš talpyklos. Jei perduodamas blokas, šis blokas bus vykdomas, jei talpykloje nėra duomenų. Bloko grąžinimo reikšmė bus įrašyta į talpyklą pagal nurodytą talpyklos raktą, ir ši grąžinimo reikšmė bus grąžinta. Jei talpykloje yra duomenų, grąžinama talpykloje esanti reikšmė be bloko vykdymo.

Svarstykite šį pavyzdį. Programoje yra „Product“ modelis su egzemplioriaus metodu, kuris ieško produkto kainos konkuruojančioje svetainėje. Šio metodo grąžinami duomenys būtų puikūs žemo lygio talpinimui:

class Product < ApplicationRecord
  def competing_price
    Rails.cache.fetch("#{cache_key_with_version}/competing_price", expires_in: 12.hours) do
      Competitor::API.find_price(id)
    end
  end
end

PASTABA: Pastebėkite, kad šiame pavyzdyje naudojome cache_key_with_version metodą, todėl gautas talpyklos raktas bus kažkas panašaus į products/233-20140225082222765838000/competing_price. cache_key_with_version sugeneruoja eilutę, remdamasi modelio klasės pavadinimu, id ir updated_at atributais. Tai yra įprasta konvencija ir turi naudą, kadangi talpykla tampa nebegaliojančia, kai produktas yra atnaujinamas. Bendrai tariant, naudojant žemo lygio talpinimą, reikia sugeneruoti talpyklos raktą.

1.7.1 Venkite „Active Record“ objektų egzempliorių talpinimo

Svarstykite šį pavyzdį, kuriame talpinama „Active Record“ objektų sąrašo, kuris atstovauja super vartotojams, talpykloje:

# super_admins yra brangi SQL užklausa, todėl jos nevykdykite per dažnai
Rails.cache.fetch("super_admin_users", expires_in: 12.hours) do
  User.super_admins.to_a
end

Turėtumėte vengti šio modelio. Kodėl? Nes egzempliorius gali pasikeisti. Producijos aplinkoje jo atributai gali skirtis arba įrašas gali būti ištrintas. O kūrimo metu tai veikia nepatikimai su talpyklų saugyklomis, kurios perkrauna kodą, kai atliekate pakeitimus.

Vietoj to, talpinkite ID ar kitą primityvų duomenų tipą. Pavyzdžiui:

# super_admins yra brangi SQL užklausa, todėl jos nevykdykite per dažnai
ids = Rails.cache.fetch("super_admin_user_ids", expires_in: 12.hours) do
  User.super_admins.pluck(:id)
end
User.where(id: ids).to_a

1.8 SQL talpinimas

Užklausos talpinimas yra „Rails“ funkcija, kuri talpina kiekvienos užklausos grąžinamą rezultatų rinkinį. Jei „Rails“ vėl susiduria su ta pačia užklausa toje pačioje užklausos metu, jis naudos talpykloje esantį rezultatų rinkinį, o ne vykdys užklausą duomenų bazėje.

Pavyzdžiui:

class ProductsController < ApplicationController
  def index
    # Vykdome užklausą
    @products = Product.all

    # ...

    # Vėl vykdome tą pačią užklausą
    @products = Product.all
  end
end

Antrą kartą, kai ta pati užklausa vykdoma duomenų bazėje, ji iš tikrųjų nebus vykdoma duomenų bazėje. Pirmą kartą rezultatas grąžinamas iš užklausos ir saugomas užklausos talpykloje (atmintyje), o antrą kartą jis gaunamas iš atminties.

Tačiau svarbu pažymėti, kad užklausos talpyklos yra sukuriamos veiksmo pradžioje ir sunaikinamos veiksmo pabaigoje, todėl jos išlieka tik veiksmo trukmės metu. Jei norite saugoti užklausos rezultatus ilgalaikiu būdu, galite tai padaryti naudodami žemo lygio talpinimą.

2 Talpyklos saugyklos

„Rails“ teikia skirtingas saugyklos talpykloje esantiems duomenims (išskyrus SQL ir puslapio talpinimą).

2.1 Konfigūracija

Galite nustatyti savo programos numatytąją talpyklos saugyklą, nustatydami config.cache_store konfigūracijos parinktį. Kiti parametrai gali būti perduodami kaip argumentai talpyklos saugyklos konstruktoriui:

config.cache_store = :memory_store, { size: 64.megabytes }

Alternatyviai, galite nustatyti ActionController::Base.cache_store už konfigūracijos bloko ribų.

Galite pasiekti talpyklą, iškviesdami Rails.cache.

2.1.1 Ryšio baseino parinktys

Pagal numatymą :mem_cache_store ir :redis_cache_store yra sukonfigūruotos naudoti ryšio baseiną. Tai reiškia, kad jei naudojate Puma ar kitą gijinį serverį, galite turėti kelias gijas, vykdančias užklausas į talpyklos saugyklą tuo pačiu metu. Jei norite išjungti ryšių kaupimą, nustatykite :pool parinktį kaip false, konfigūruodami talpyklą:

config.cache_store = :mem_cache_store, "cache.example.com", pool: false

Taip pat galite perrašyti numatytuosius kaupimo nustatymus, pateikdami atskiras parinktis :pool parinktyje:

config.cache_store = :mem_cache_store, "cache.example.com", pool: { size: 32, timeout: 1 }
  • :size - Ši parinktis nustato ryšių skaičių vienam procesui (numatytoji reikšmė yra 5).

  • :timeout - Ši parinktis nustato laukimo sekundes ryšiui (numatytoji reikšmė yra 5). Jei per laukimo laikotarpį nėra prieinamo ryšio, bus iškelta Timeout::Error klaida.

2.2 ActiveSupport::Cache::Store

ActiveSupport::Cache::Store suteikia pagrindą sąveikai su talpykla „Rails“. Tai yra abstrakti klasė, ir jos negalima naudoti atskirai. Vietoj to, turite naudoti konkretų klasės įgyvendinimą, susietą su saugojimo varikliu. „Rails“ pristato keletą įgyvendinimų, aprašytų žemiau.

Pagrindiniai API metodai yra read, write, delete, exist? ir fetch.

Talpyklos saugojimo konstruktoriui perduodamos parinktys bus laikomos numatytosiomis parinktimis atitinkamiems API metodams.

2.3 ActiveSupport::Cache::MemoryStore

ActiveSupport::Cache::MemoryStore laiko įrašus atmintyje toje pačioje „Ruby“ procese. Talpyklos saugojimo dydis yra ribotas, nurodant :size parinktį pradinėje funkcijoje (numatytoji reikšmė yra 32 MB). Kai talpykla viršija nustatytą dydį, vyksta valymas ir pašalinami mažiausiai naudojami įrašai.

config.cache_store = :memory_store, { size: 64.megabytes }

Jei naudojate kelis „Ruby on Rails“ serverio procesus (kas yra atvejis, jei naudojate „Phusion Passenger“ arba „puma“ klasterizuotą režimą), tada jūsų „Rails“ serverio procesų egzemplioriai negalės dalintis talpyklos duomenimis. Ši talpykla nėra tinkama dideliems programų diegimams. Tačiau ji gali gerai veikti mažose, mažai lankomose svetainėse su tik keletu serverio procesų, taip pat plėtros ir testavimo aplinkose.

Naujiems „Rails“ projektams numatytasis įgyvendinimas yra naudojamas vystymo aplinkoje.

PASTABA: Naudodami :memory_store, procesai nesidalins talpyklos duomenimis, tai neleis rankiniu būdu skaityti, rašyti arba panaikinti talpyklą per „Rails“ konsolę.

2.4 ActiveSupport::Cache::FileStore

ActiveSupport::Cache::FileStore naudoja failų sistemą įrašams saugoti. Nurodykite kelią į katalogą, kuriame bus saugomi saugojimo failai, inicializuojant talpyklą.

config.cache_store = :file_store, "/path/to/cache/directory"

Šiai talpyklai kelios serverio procesai tame pačiame prietaise gali dalintis talpykla. Ši talpykla yra tinkama mažai ir vidutinės apimties svetainėms, kurios aptarnaujamos vienoje ar dviejose prietaisų. Skirtinguose prietaisuose veikiantys serverio procesai galėtų dalintis talpykla, naudodami bendrą failų sistemą, tačiau ši sąranka nerekomenduojama.

Kadangi talpykla augs, kol bus užpildytas diskas, rekomenduojama periodiškai išvalyti senus įrašus.

Tai yra numatytasis talpyklos įgyvendinimas (esant "#{root}/tmp/cache/"), jei nėra pateikta aiški config.cache_store.

2.5 ActiveSupport::Cache::MemCacheStore

ActiveSupport::Cache::MemCacheStore naudoja Dangos memcached serverį, kad suteiktų centralizuotą talpyklą jūsų programai. „Rails“ pagal numatymą naudoja įtrauktą dalli grotelę. Tai šiuo metu populiariausia talpyklos įgyvendinimas produktų svetainėms. Jis gali būti naudojamas suteikiant vieną bendrą talpyklų klasterį su labai dideliu našumu ir atsparumu.

Inicializuojant talpyklą, turėtumėte nurodyti visų memcached serverių adresus savo klasteryje arba užtikrinti, kad būtų tinkamai nustatyta MEMCACHE_SERVERS aplinkos kintamoji.

config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com"

Jei nenurodoma nei viena, jis priims, kad memcached veikia „localhost“ numatytuoju prievadu (127.0.0.1:11211), tačiau tai nėra idealus sąranka didesnėms svetainėms.

config.cache_store = :mem_cache_store # Atsarginė vertė bus $MEMCACHE_SERVERS, tada 127.0.0.1:11211

Peržiūrėkite Dalli::Client dokumentaciją palaikomoms adreso tipams.

Šiai talpyklai write (ir fetch) metodas priima papildomas parinktis, kurios naudojasi memcached specifinėmis funkcijomis.

2.6 ActiveSupport::Cache::RedisCacheStore

ActiveSupport::Cache::RedisCacheStore naudoja „Redis“ palaikymą automatiniam išmetimui pasiekus maksimalią atmintį, leidžiant jai elgtis panašiai kaip „Memcached“ talpyklos serveris.

Diegimo pastaba: „Redis“ pagal numatymą nebaigia galiojimo laiko, todėl atidžiai naudokite skirtą „Redis“ talpyklą. Neužpildykite savo nuolatinio „Redis“ serverio nestabiliais talpyklos duomenimis! Išsamiai perskaitykite Redis talpyklos serverio diegimo vadovą.

Tik talpyklai skirtame „Redis“ serveryje nustatykite maxmemory-policy vienam iš „allkeys“ variantų. „Redis“ 4+ palaiko mažiausiai dažnai naudojamą išmetimą (allkeys-lfu), puikus numatytasis pasirinkimas. „Redis“ 3 ir ankstesnės versijos turėtų naudoti mažiausiai neseniai naudojamą išmetimą (allkeys-lru). Nustatykite talpyklos skaitymo ir rašymo laiko limitus santykinai mažus. Dažnai atkurti talpykloje saugomą reikšmę yra greičiau nei laukti ilgiau nei sekundę, kad ją gautumėte. Skaitymo ir rašymo laiko limitai pagal nutylėjimą yra 1 sekundė, bet juos galima nustatyti dar mažesnius, jei jūsų tinklas yra nuolat mažo delsimo.

Pagal nutylėjimą, jei ryšys su Redis nutrūksta per užklausą, talpyklos saugojimas nebandys vėl prisijungti. Jei dažnai patiriate atsijungimus, galite įjungti prisijungimo bandymus.

Talpyklos skaitymas ir rašymas niekada nekelia išimčių; jie tiesiog grąžina nil, elgdamiesi taip, tarsi talpykloje nieko nebūtų. Norėdami įvertinti, ar jūsų talpykla sukelia išimtis, galite nurodyti error_handler, kuris praneš apie išimtis rinkimo paslaugai. Jis turi priimti tris raktažodžius: method, talpyklos saugojimo metodą, kuris buvo iš pradžių iškviestas; returning, grąžintą reikšmę vartotojui, paprastai nil; ir exception, išimtį, kuri buvo išgelbėta.

Norėdami pradėti, pridėkite redis juostelę prie savo Gemfile:

gem 'redis'

Galų gale, pridėkite konfigūraciją atitinkamame config/environments/*.rb faile:

config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'] }

Sudėtingesnė, gamybinė Redis talpyklos saugykla gali atrodyti taip:

cache_servers = %w(redis://cache-01:6379/0 redis://cache-02:6379/0)
config.cache_store = :redis_cache_store, { url: cache_servers,

  connect_timeout:    30,  # Numatytasis yra 20 sekundės
  read_timeout:       0.2, # Numatytasis yra 1 sekundė
  write_timeout:      0.2, # Numatytasis yra 1 sekundė
  reconnect_attempts: 1,   # Numatytasis yra 0

  error_handler: -> (method:, returning:, exception:) {
    # Praneškite apie klaidas "Sentry" kaip įspėjimus
    Sentry.capture_exception exception, level: 'warning',
      tags: { method: method, returning: returning }
  }
}

2.7 ActiveSupport::Cache::NullStore

ActiveSupport::Cache::NullStore yra apribota kiekvienai interneto užklausai ir valo saugomas reikšmes užklausos pabaigoje. Ji skirta naudoti vystymo ir testavimo aplinkose. Tai gali būti labai naudinga, kai turite kodą, kuris tiesiogiai sąveikauja su Rails.cache, bet talpykla trukdo matyti kodų pakeitimų rezultatus.

config.cache_store = :null_store

2.8 Individualios talpyklos saugyklos

Galite sukurti savo individualią talpyklos saugyklą, tiesiog išplėsdami ActiveSupport::Cache::Store ir įgyvendindami atitinkamus metodus. Taip galite į savo „Rails“ programą įtraukti bet kurią talpinimo technologiją.

Norėdami naudoti individualią talpyklos saugyklą, tiesiog nustatykite talpyklos saugyklą kaip naują savo individualios klasės egzempliorių.

config.cache_store = MyCacheStore.new

3 Talpyklos raktai

Talpykloje naudojami raktai gali būti bet koks objektas, kuris atsako į cache_key arba to_param metodus. Jei norite generuoti individualius raktus, savo klasėse galite įgyvendinti cache_key metodą. „Active Record“ sugeneruos raktus pagal klasės pavadinimą ir įrašo ID.

Galite naudoti raktus kaip reikšmių talpyklos raktus.

# Tai yra teisėtas talpyklos raktas
Rails.cache.read(site: "mysite", owners: [owner_1, owner_2])

Raktai, kuriuos naudojate Rails.cache, nebus tokie patys kaip tie, kurie iš tikrųjų naudojami saugojimo variklyje. Jie gali būti modifikuojami su pavadinimo erdve arba keičiami, kad atitiktų technologijos pagrindo apribojimus. Tai reiškia, pavyzdžiui, kad negalite išsaugoti reikšmių su Rails.cache ir tada bandyti ištraukti jas su dalli juostele. Tačiau taip pat nereikia nerimauti dėl viršijimo „memcached“ dydžio ribos arba pažeidimo sintaksės taisyklių.

4 Sąlyginio GET palaikymas

Sąlyginis GET yra „HTTP“ specifikacijos funkcija, kuri leidžia interneto serveriams pranešti naršyklėms, kad atsakymas į GET užklausą nepasikeitė nuo paskutinės užklausos ir gali būti saugiai paimtas iš naršyklės talpyklos.

Jie veikia naudojant HTTP_IF_NONE_MATCH ir HTTP_IF_MODIFIED_SINCE antraštes, kad perduotų atgal ir į priekį unikalų turinio identifikatorių ir laiko žymą, kada turinys buvo paskutinį kartą pakeistas. Jei naršyklė atlieka užklausą, kurioje turinio identifikatorius (ETag) arba paskutinio pakeitimo laiko žyma atitinka serverio versiją, tada serveriui tereikia grąžinti tuščią atsakymą su nekeista būsena.

Tai yra serverio (t. y. mūsų) atsakomybė ieškoti paskutinio pakeitimo laiko žymos ir if-none-match antraštės ir nustatyti, ar grąžinti visą atsakymą. Su sąlyginio-get palaikymu „Rails“ tai yra gana paprasta užduotis:

class ProductsController < ApplicationController
  def show
    @product = Product.find(params[:id])

    # Jei užklausa yra pasenusi pagal nurodytą laiko žymą ir etag reikšmę
    # (t. y. ją reikia iš naujo apdoroti), tada vykdykite šį bloką
    if stale?(last_modified: @product.updated_at.utc, etag: @product.cache_key_with_version)
      respond_to do |wants|
        # ... įprasta atsakymo apdorojimas
      end
    end

    # Jei užklausa yra nauja (t. y. ji nepakeista), tada jums nereikia nieko daryti.
    # Numatytasis renderis tai patikrina naudodamas parametrus,
    # naudotus ankstesniam stale? iškvietimui, ir automatiškai siunčia
    # :not_modified. Tai viskas, jūs baigėte.
  end
end

Vietoj parinkčių hash galite tiesiogiai perduoti modelį. „Rails“ naudos „updated_at“ ir „cache_key_with_version“ metodus nustatant „last_modified“ ir „etag“:

class ProductsController < ApplicationController
  def show
    @product = Product.find(params[:id])

    if stale?(@product)
      respond_to do |wants|
        # ... įprasta atsakymo apdorojimo logika
      end
    end
  end
end

Jei neturite jokio specialaus atsakymo apdorojimo ir naudojate numatytąjį atvaizdavimo mechanizmą (t. y. nenaudojate „respond_to“ arba pačių kviečiate „render“), tada turite lengvą pagalbininką „fresh_when“:

class ProductsController < ApplicationController
  # Jei užklausa yra nauja, tai automatiškai bus grąžintas :not_modified,
  # o jei ji yra pasenusi, bus atvaizduotas numatytasis šablonas (product.*).

  def show
    @product = Product.find(params[:id])
    fresh_when last_modified: @product.published_at.utc, etag: @product
  end
end

Kartais norime talpinti atsakymą, pvz., statinį puslapį, kuris niekada nesibaigia. Tam pasiekti galime naudoti „http_cache_forever“ pagalbininką, ir taip naršyklė ir tarpinės atmintys jį talpins amžinai.

Pagal numatytuosius nustatymus talpinami atsakymai bus privačūs, talpinami tik vartotojo naršyklėje. Norint leisti tarpinėms atmintims talpinti atsakymą, nustatykite „public: true“, nurodydami, kad jos gali aptarnauti talpintą atsakymą visiems vartotojams.

Naudodami šį pagalbininką, „last_modified“ antraštė bus nustatyta į „Time.new(2011, 1, 1).utc“, o „expires“ antraštė bus nustatyta į 100 metų.

ĮSPĖJIMAS: Šią metodą naudokite atsargiai, nes naršyklės/tarpinės atmintys negalės atšaukti talpinto atsakymo, nebent naršyklės talpyklą būtų priverstinai išvalyta.

class HomeController < ApplicationController
  def index
    http_cache_forever(public: true) do
      render
    end
  end
end

4.1 Stiprūs prieš silpnus ETag

Pagal numatytuosius nustatymus „Rails“ generuoja silpnus ETag. Silpni ETag leidžia semantiškai ekvivalentiškiems atsakymams turėti tą pačią ETag, net jei jų kūnai nesutampa tiksliai. Tai naudinga, kai norime, kad puslapis nebūtų pergeneruojamas dėl nedidelių pakeitimų atsakymo kūne.

Silpni ETag turi pradžioje „W/“, kad juos būtų galima atskirti nuo stiprių ETag.

W/"618bbc92e2d35ea1945008b42799b0e7" → Silpnas ETag
"618bbc92e2d35ea1945008b42799b0e7" → Stiprus ETag

Skirtingai nei silpnas ETag, stiprus ETag reiškia, kad atsakymas turi būti tiksliai tas pats ir baitais identiškas. Tai naudinga, kai darome diapazono užklausas didelio vaizdo ar PDF failo viduje. Kai kurios CDN palaiko tik stiprius ETag, pvz., „Akamai“. Jei absoliučiai reikia generuoti stiprų ETag, tai galima padaryti taip.

class ProductsController < ApplicationController
  def show
    @product = Product.find(params[:id])
    fresh_when last_modified: @product.published_at.utc, strong_etag: @product
  end
end

Stiprų ETag taip pat galite nustatyti tiesiogiai atsakyme.

response.strong_etag = response.body # => "618bbc92e2d35ea1945008b42799b0e7"

5 Talpinimas vystymo metu

Dažnai norime patikrinti savo programos talpinimo strategiją vystymo metu. „Rails“ teikia „rails“ komandą „dev:cache“, skirtą lengvai įjungti/išjungti talpinimą.

$ bin/rails dev:cache
Vystymo režimas dabar talpinamas.
$ bin/rails dev:cache
Vystymo režimas nebėra talpinamas.

Pagal numatytuosius nustatymus, kai vystymo režimo talpinimas yra išjungtas, „Rails“ naudoja :null_store.

6 Nuorodos

Atsiliepimai

Jūs esate skatinami padėti pagerinti šio vadovo kokybę.

Prašome prisidėti, jei pastebite rašybos klaidų ar faktinių klaidų. Norėdami pradėti, galite perskaityti mūsų dokumentacijos prisidėjimo skyrių.

Taip pat gali būti nepilnos informacijos arba informacijos, kuri nėra atnaujinta. Prašome pridėti bet kokią trūkstamą dokumentaciją pagrindiniam. Patikrinkite Edge vadovus pirmiausia, ar problemas jau išspręsta arba ne pagrindinėje šakoje. Patikrinkite Ruby on Rails vadovų gaires dėl stiliaus ir konvencijų.

Jei dėl kokios nors priežasties pastebite kažką, ką reikia ištaisyti, bet negalite patys tai pataisyti, prašome pranešti apie problemą.

Ir galiausiai, bet ne mažiau svarbu, bet koks diskusijos dėl Ruby on Rails dokumentacijos yra labai laukiamos oficialiame Ruby on Rails forume.