कैशिंग का वर्णन करने का एक सामान्य तरीका कुछ डेटा संग्रहीत करना है ताकि हम इसे बाद में जल्दी से प्राप्त कर सकें। कभी-कभी, इसका अर्थ है गणना किए गए डेटा को संग्रहीत करना ताकि इसे फिर से गणना करने की आवश्यकता न हो, लेकिन यह डेटा को फिर से लाने से बचने के लिए स्थानीय रूप से संग्रहीत करने का भी उल्लेख कर सकता है। आपका कंप्यूटर लगातार ऐसा करता है, क्योंकि आपका ऑपरेटिंग सिस्टम रैम में बार-बार एक्सेस किए जाने वाले डेटा को रखने की कोशिश करता है ताकि इसे फिर से हार्ड ड्राइव या एसएसडी से प्राप्त न करना पड़े।
इसी तरह, आपका ब्राउज़र पहले से डाउनलोड किए गए संसाधनों का पुन:उपयोग करने का प्रयास करता है। पहली बार किसी नई वेबसाइट पर जाने पर आपने शायद इसे स्वयं देखा होगा। आरंभिक लोड में अधिक समय लगता है क्योंकि आपके ब्राउज़र को सब कुछ को नीचे खींचना होता है इसकी जरूरत है, सभी छवियों, जावास्क्रिप्ट और स्टाइलशीट सहित। एक मजेदार तथ्य यह है कि जब आप सीएनएन होमपेज को नए सिरे से डाउनलोड करते हैं, तो आपका ब्राउज़र मूल डूम गेम की तुलना में 1993 के आसपास अधिक डेटा प्राप्त करता है। जिज्ञासु के लिए, इस ब्लॉग पोस्ट को लिखते समय, सीएनएन मेरी मशीन पर सिर्फ 3 एमबी से अधिक डाउनलोड करता है, से संपीड़ित ~15MB, और वह है एक विज्ञापन अवरोधक सक्षम होने के साथ, जबकि मूल डूम इंस्टॉलर ~2.2MB था।
इस डेटा को कैश करने के लिए ब्राउज़र के लिए सर्वर के साथ कुछ समन्वय होना चाहिए। ब्राउज़र को यह जानने की जरूरत है कि वह क्या कैश कर सकता है और कितने समय तक; अन्यथा, सर्वर के पास एक नया संस्करण उपलब्ध होने पर यह आपको पुरानी सामग्री दिखा सकता है। इस लेख में, हम देखेंगे कि यह क्लाइंट-सर्वर कैशिंग समन्वय कैसे किया जाता है और इसे बदलने के लिए रेल क्या प्रदान करता है।
यद्यपि ध्यान इस बात पर है कि रूबी ऑन रेल्स इसे कैसे संभालता है, वास्तविक तंत्र HTTP विनिर्देशों का हिस्सा है। दूसरे शब्दों में, हम यहां जिस कैशिंग के बारे में बात कर रहे हैं, वह इंटरनेट के बुनियादी ढांचे में बेक की गई है, जो इसे आधुनिक वेबसाइटों और ढांचे के विकास की आधारशिला बनाती है। विभिन्न ढांचे, जैसे रेल, सिंगल-पेज एप्लिकेशन (एसपीए), और यहां तक कि स्थिर साइटें, सभी इन तंत्रों का उपयोग प्रदर्शन को बेहतर बनाने में मदद के लिए कर सकते हैं।
HTTP अनुरोध-प्रतिक्रिया
आप शायद अनुरोध-प्रतिक्रिया जीवनचक्र से परिचित हैं, कम से कम उच्च स्तर पर:आप किसी वेबसाइट पर एक लिंक पर क्लिक करते हैं, आपका ब्राउज़र उस सामग्री के लिए सर्वर को एक अनुरोध भेजता है, और सर्वर उस सामग्री को वापस भेजता है (ध्यान दें कि मैं मैं यहाँ बहुत सारी जटिलताओं को जान-बूझकर दिखा रहा हूँ)।
आइए इस आगे-पीछे के लेन-देन में भेजे जा रहे वास्तविक डेटा में थोड़ा खुदाई करें। प्रत्येक HTTP संदेश में एक हेडर और एक बॉडी होती है (<head>
. के साथ भ्रमित नहीं होना चाहिए और <body>
एचटीएमएल टैग)। अनुरोध शीर्षलेख सर्वर को बताता है कि आप किस पथ तक पहुंचने का प्रयास कर रहे हैं और किस HTTP विधि का उपयोग करना है (उदाहरण के लिए, प्राप्त/पुट/पैच/पोस्ट)। यदि आवश्यक हो, तो आप अपने ब्राउज़र के डेवलपर टूल या कमांड-लाइन टूल, जैसे curl
का उपयोग करके इन शीर्षलेखों में खुदाई कर सकते हैं :
# curl -v honeybadger.io
...
> GET / HTTP/1.1
> Host: honeybadger.io
> User-Agent: curl/7.64.1
> Accept: */*
आउटपुट का यह पहला भाग अनुरोध शीर्षलेख है। हम एक GET
जारी कर रहे हैं करने के लिए honeybadger.io
. इसके बाद सर्वर ने क्या भेजा ("प्रतिक्रिया शीर्षलेख"):
>
< HTTP/1.1 301 Moved Permanently
< Cache-Control: public, max-age=0, must-revalidate
< Content-Length: 39
< Content-Security-Policy: frame-ancestors 'none'
...
< Content-Type: text/plain
प्रतिक्रिया में HTTP कोड शामिल होता है (उदा., 200
सफलता के लिए या 404
के लिए नहीं मिला)। इस उदाहरण में, यह एक स्थायी रीडायरेक्ट (301) है क्योंकि कर्ल http
. से संपर्क करने का प्रयास कर रहा है यूआरएल, जो सुरक्षित https
. पर रीडायरेक्ट करता है URL.प्रतिक्रिया शीर्षलेख में सामग्री प्रकार भी शामिल है, जो text/plain
है यहाँ, लेकिन कुछ अन्य सामान्य विकल्प हैं text/html
, text/css
, text/javascript
, और application/json
।
प्रतिक्रिया निकाय हेडर का अनुसरण करता है। हमारे मामले में, शरीर खाली है क्योंकि एक 301
रीडायरेक्ट को शरीर की आवश्यकता नहीं है। अगर हमने curl -v https://www.honeybadger.io
. के साथ फिर से कोशिश की , आपको यहां मुखपृष्ठ सामग्री दिखाई देगी, ठीक वैसे ही जैसे आप किसी ब्राउज़र में स्रोत देख रहे थे।
यदि आप स्वयं इसका प्रयोग करना चाहते हैं तो यहां दो युक्तियां दी गई हैं:
- केवल कर्ल के साथ प्रतिक्रिया शीर्षलेख दिखाने के लिए (उदाहरण के लिए, कोई अनुरोध शीर्षलेख या प्रतिक्रिया निकाय नहीं),
-I
का उपयोग करें विकल्प, जैसा किcurl -I localhost:3000
में है । - डिफ़ॉल्ट रूप से, रेल विकास के माहौल में कैश नहीं करता है; आपको
rails dev:cache
चलाने की आवश्यकता हो सकती है पहले।
कैश-कंट्रोल HTTP हैडर
जहां तक कैशिंग की बात है, हम जिस मुख्य हेडर की परवाह करते हैं, वह है Cache-Control
शीर्षलेख। यह निर्धारित करने में मदद करता है कि कौन सी मशीनें हमारे रेल सर्वर से प्रतिक्रिया को कैश कर सकती हैं और जब वह कैश्ड डेटा समाप्त हो जाता है। Cache-Control
के अंदर शीर्षलेख, कई फ़ील्ड हैं, जिनमें से अधिकांश वैकल्पिक हैं। हम यहां कुछ सबसे प्रासंगिक प्रविष्टियों के माध्यम से जाएंगे, लेकिन अधिक जानकारी के लिए, आप आधिकारिक HTTP विनिर्देश w3.org पर देख सकते हैं।
बुनियादी आउट-ऑफ़-द-बॉक्स रेल प्रतिक्रिया शीर्षलेख से एक नमूना यहां दिया गया है:
< Content-Type: text/html; charset=utf-8
< Etag: W/"b41ce6c6d4bde17fd61a09e36b1e52ad"
< Cache-Control: max-age=0, private, must-revalidate
अधिकतम-आयु
max-age
फ़ील्ड एक पूर्णांक है जिसमें प्रतिक्रिया मान्य होने वाले सेकंड की संख्या होती है। डिफ़ॉल्ट रूप से, एक दृश्य के लिए एक रेल प्रतिक्रिया में यह 0 पर सेट होगा (यानी, प्रतिक्रिया तुरंत समाप्त हो जाती है, और ब्राउज़र को हमेशा एक नया संस्करण मिलना चाहिए)।
सार्वजनिक/निजी
public
. सहित या private
हेडर सेट में किन सर्वरों को प्रतिक्रिया को कैश करने की अनुमति है। यदि शीर्षलेख में private
शामिल है , इसे केवल अनुरोध करने वाले क्लाइंट (उदाहरण के लिए, ब्राउज़र) द्वारा कैश किया जाना है, न कि किसी अन्य सर्वर से जो इसे प्राप्त करने के लिए गुजरा हो, जैसे कि सामग्री वितरण नेटवर्क (सीडीएन) या प्रॉक्सी। यदि शीर्षलेख में public
शामिल है , तो इन मध्यस्थ सर्वरों को प्रतिक्रिया को कैश करने की अनुमति है। रेल प्रत्येक शीर्षलेख को private
. पर सेट करती है डिफ़ॉल्ट रूप से।
अत्यावश्यक-पुनरीक्षित करें
रेल्स must-revalidate
भी सेट करते हैं डिफ़ॉल्ट रूप से फ़ील्ड। इसका अर्थ यह है कि क्लाइंट को यह पुष्टि करने के लिए सर्वर से संपर्क करना चाहिए कि इसका कैश्ड संस्करण उपयोग किए जाने से पहले अभी भी मान्य है। यह निर्धारित करने के लिए कि कैश्ड संस्करण मान्य है, क्लाइंट और सर्वर ईटैग का उपयोग करते हैं।
ईटैग
ईटैग एक वैकल्पिक HTTP शीर्षलेख है जो सर्वर द्वारा तब जोड़ा जाता है जब यह क्लाइंट को प्रतिक्रिया भेजता है। आमतौर पर, यह प्रतिक्रिया पर ही किसी प्रकार का चेकसम होता है। जब क्लाइंट (यानी, आपके ब्राउज़र) को इस संसाधन के लिए फिर से अनुरोध करने की आवश्यकता होती है, तो इसमें If-None-Match
में इसे प्राप्त एटैग (यह मानते हुए कि इसकी पिछली प्रतिक्रिया कैश की गई है) शामिल है। HTTP हेडर। सर्वर तब 304
. के साथ प्रतिसाद दे सकता है HTTP कोड ("संशोधित नहीं") और एक खाली बॉडी। इसका मतलब है कि सर्वर पर संस्करण नहीं बदला है, इसलिए क्लाइंट को इसके कैश्ड संस्करण का उपयोग करना चाहिए।
ईटैग दो प्रकार के होते हैं:मजबूत और कमजोर (एक कमजोर टैग को W/
से दर्शाया जाता है। उपसर्ग)। वे उसी तरह व्यवहार करते हैं, लेकिन एक मजबूत ईटीएजी का मतलब है कि संसाधन की दो प्रतियां (सर्वर पर संस्करण और स्थानीय कैश में एक) 100% बाइट-फॉर-बाइट समान हैं। कमजोर ईटैग, हालांकि, इंगित करते हैं कि दो प्रतियां बाइट-दर-बाइट समान नहीं हो सकती हैं, लेकिन कैश्ड संस्करण का अभी भी उपयोग किया जा सकता है। इसका एक सामान्य उदाहरण है रेल्स का csrf_meta_tags
सहायक, जो एक टोकन बनाता है जो लगातार बदलता रहता है; इस प्रकार, भले ही आपके आवेदन में एक स्थिर पृष्ठ हो, क्रॉस-साइट-अनुरोध-जालसाजी (सीएसआरएफ) टोकन के कारण रीफ्रेश होने पर यह बाइट-फॉर-बाइट समान नहीं होगा। रेल डिफ़ॉल्ट रूप से कमजोर ईटैग का उपयोग करती है।
रेल में Etags
रेल स्वचालित रूप से विचारों पर ईटैग को संभालती है। इसमें आउटगोइंग हेडर में ETag शामिल है और इसमें आने वाले ETag हेडर की जांच करने के लिए मिडलवेयर है और 304
लौटाता है (संशोधित नहीं) कोड जब उपयुक्त हो। विशेष रूप से, हालांकि, क्योंकि रेल गतिशील रूप से विचार उत्पन्न करता है, इससे पहले कि वह उस दृश्य के लिए ईटीएजी को समझ सके, उसे अभी भी सभी प्रतिपादन कार्य करना होगा। इसका मतलब यह है कि भले ही ईटैग मेल खाते हों, आप केवल उस समय और बैंडविड्थ की बचत कर रहे हैं, जो पूरे नेटवर्क में डेटा भेजने में लगता है, जैसा कि व्यू कैशिंग जैसी किसी चीज के विपरीत है, जहां कैश्ड संस्करण होने पर आप रेंडरिंग चरण को पूरी तरह से छोड़ सकते हैं। हालाँकि, रेल जनरेट किए गए ETag को बदलने के लिए कुछ तरीके प्रदान करता है।
बासी?
ETag को बदलने से हमेशा बदलते CSRF टोकन को दूर करने का एक तरीका stale?
के साथ है ActionController
में सहायक . यह आपको सीधे ETag (या तो मजबूत या कमजोर) सेट करने की अनुमति देता है। हालांकि, आप इसे केवल एक ऑब्जेक्ट पास कर सकते हैं, जैसे कि एक ActiveRecord मॉडल, और यह ऑब्जेक्ट के updated_at
के आधार पर ETag की गणना करेगा। टाइमस्टैम्प या अधिकतम updated_at
. का उपयोग करें अगर आप कोई संग्रह पास करते हैं:
class UsersController < ApplicationController
def index
@users = User.includes(:posts).all
render :index if stale?(@users)
end
end
पृष्ठ को कर्ल से मारकर, हम परिणाम देख सकते हैं:
# curl -I localhost:3000 -- first page load
ETag: W/"af9ae8f2d66b9b6c4d0513f185638f1a"
# curl -I localhost:3000 -- reload (change due to CSRF token)
ETag: W/"f06158417f290334f47ea2124e08d89d"
-- Add stale? to controller code
# curl -I localhost:3000 -- reload
ETag: W/"04b9b99835c359f36551720d8e3ca6fe" -- now using `@users` to generate ETag
# curl -I localhost:3000 -- reload
ETag: W/"04b9b99835c359f36551720d8e3ca6fe" -- no change
यह हमें उस पर अधिक नियंत्रण देता है जब क्लाइंट को फिर से पूरा पेलोड डाउनलोड करना होता है, लेकिन उसे अभी भी सर्वर से हर बार जांचना पड़ता है। यह निर्धारित करने के लिए कि इसका कैश अभी भी मान्य है या नहीं। क्या होगा अगर हम उस चेक को पूरी तरह से छोड़ना चाहते हैं? यह वह जगह है जहां max-age
हेडर में फ़ील्ड आता है।
समाप्त_इन और http_cache_forever
रेल हमें ActionController
. में कुछ सहायक तरीके प्रदान करती है max-age
को समायोजित करने के लिए फ़ील्ड:expires_in
और http_cache_forever
. वे दोनों काम करते हैं कि आप उनके नाम के आधार पर क्या उम्मीद करेंगे:
class UsersController < ApplicationController
def index
@users = User.includes(:posts).all
expires_in 10.minutes
end
end
# curl -I localhost:3000
Cache-Control: max-age=600, private
रेल ने max-age
सेट किया है 600 (सेकंड में 10 मिनट) तक और must-revalidate
. को हटा दिया खेत। आप private
भी बदल सकते हैं public: true
. पास करके फ़ील्ड नामित तर्क।
http_cache_forever
ज्यादातर expires_in
. के आसपास सिर्फ एक आवरण है जो max-age
सेट करता है 100 साल तक और एक ब्लॉक लेता है:
class UsersController < ApplicationController
def index
@users = User.includes(:posts).all
http_cache_forever(public: true) do
render :index
end
end
end
# curl -I localhost:3000
Cache-Control: max-age=3155695200, public
इस प्रकार की अत्यंत-दीर्घकालिक-कैशिंग यही कारण है कि रेल की संपत्ति में एक "फिंगरप्रिंट" जोड़ा जाता है, जो फ़ाइल की सामग्री का हैश है और फ़ाइल नाम बनाता है, जैसे कि packs/js/application-4028feaf5babc1c1617b.js
. अंत में "फिंगरप्रिंट" फ़ाइल की सामग्री को फ़ाइल के नाम से प्रभावी ढंग से जोड़ता है। यदि सामग्री कभी बदलती है, तो फ़ाइल नाम बदल जाएगा। इसका अर्थ है कि ब्राउज़र इस फ़ाइल को हमेशा के लिए सुरक्षित रूप से कैश कर सकते हैं क्योंकि अगर यह कभी बदलता है, तो एक छोटे से तरीके से भी, फिंगरप्रिंट बदल जाएगा; जहां तक ब्राउज़र का संबंध है, यह एक पूरी तरह से अलग फ़ाइल है जिसे डाउनलोड करने की आवश्यकता है।
क्षेत्रों का प्रभाव
अब जबकि हमने कुछ कैशिंग विकल्पों को शामिल कर लिया है, मेरी सलाह थोड़ी अजीब लग सकती है, लेकिन मेरा सुझाव है कि आप इस आलेख में किसी भी तरीके का उपयोग करने से बचने का प्रयास करें! ईटैग और एचटीटीपी कैशिंग के बारे में जानना अच्छा है, और रेल हमें विशिष्ट समस्याओं के समाधान के लिए कुछ विशिष्ट उपकरण प्रदान करता है। चेतावनी, हालांकि, और यह एक बड़ी बात है, यह सभी कैशिंग आपके आवेदन के बाहर होती है और इसलिए, काफी हद तक आपके नियंत्रण से बाहर है। यदि आप रेल में व्यू कैशिंग या निम्न-स्तरीय कैशिंग का उपयोग कर रहे हैं, जैसा कि इस श्रृंखला के पहले के हिस्सों में शामिल किया गया है, और अमान्यता के मुद्दों का सामना करते हैं, तो आपके पास विकल्प हैं; आप touch
कर सकते हैं मॉडल, अपडेट किए गए कोड को पुश करें, या यहां तक कि Rails.cache
. तक पहुंचें यदि आपको करना है तो सीधे कंसोल से, लेकिन HTTP कैशिंग के साथ नहीं। व्यक्तिगत रूप से, मुझे Rails.cache.clear
चलाने के बजाय बहुत कुछ करना होगा उत्पादन में एक समस्या का सामना करना पड़ता है जहां उपयोगकर्ताओं के लिए साइट तब तक टूट जाती है जब तक कि वे अपना ब्राउज़र कैश साफ़ नहीं कर देते (आपकी ग्राहक सेवा टीम आपको इसके लिए भी प्यार करेगी)।
निष्कर्ष
यह रेल में कैशिंग पर श्रृंखला का अंत है; उम्मीद है, यह उपयोगी और जानकारीपूर्ण था। कैशिंग के लिए मेरी सलाह इस प्रकार है:जितना हो सके उतना कम करें, लेकिन जितना आपको करना है उतना करें। यदि आप प्रदर्शन समस्याओं का अनुभव करते हैं, तो उन तरीकों की तलाश शुरू करें जो अक्सर हिट होते हैं; शायद, उन्हें याद किया जा सकता है। अनुरोधों में बने रहने के लिए मूल्य की आवश्यकता है? हो सकता है कि अत्यधिक उपयोग की जाने वाली विधि कुछ निम्न-स्तरीय कैशिंग का उपयोग कर सके। या, शायद, यह कोई विशेष तरीका नहीं है; यह सिर्फ उन सभी नेस्टेड पार्टिकल्स के माध्यम से क्रंच कर रहा है, जो चीजों को धीमा कर रहे हैं; इस मामले में, शायद देखें स्तर कैशिंग मदद कर सकता है। इनमें से प्रत्येक मुद्दे को लक्षित करने के लिए रेल हमें "तेज चाकू" देता है, और हमें केवल यह जानना होगा कि उनका उपयोग कब करना है।