<पी> रेडिस के लिए अपस्टैश और परफॉर्मेंस एपीआई पर इस लेख में, हम देखते हैं कि आप डेनो ऐप में रेडिस के लिए अपस्टैश का सबसे अच्छा उपयोग कैसे कर सकते हैं। रेडिस के लिए अपस्टैश सर्वर-साइड कैशिंग के लिए एक सर्वर रहित डेटाबेस आदर्श है . मैं जिस वेब ऐप पर काम कर रहा था वह प्रारंभिक सर्वर रिस्पांस टाइम पर खराब स्कोर कर रहा था . लाइटहाउस 500 ms रिपोर्ट कर रहा था . अपस्टैश कैश जोड़कर मैंने इसे 150 ms से नीचे ले लिया और ऑडिट पास कर लिया. कठिन हिस्सा कैश जोड़ना नहीं था; जैसा कि होता है, कैश का उपयोग कहां करना है यह महत्वपूर्ण था। केवल प्रदर्शन को मापकर ही मैं अड़चन की पहचान कर पाया न्यूनतम कार्य के साथ प्रदर्शन को बढ़ावा देने के लिए। हम इस लेख में प्रदर्शन माप पर बारीकी से नज़र डालेंगे। <पी> मेरा प्रोजेक्ट एक डेनो फ्रेश वेब ऐप था। डेनो के पास तत्काल निर्माण और तैनाती है। यह इसे अनुकूलन के लिए काम करने के लिए एक स्वप्निल वातावरण बनाता है। फीडबैक लूप छोटा है. आप किसी अनुकूलन को स्थानीय रूप से कोड कर सकते हैं, उसे सर्वर पर भेज सकते हैं और दूरस्थ साइट का तुरंत परीक्षण करने में सक्षम हो सकते हैं। ढेर
<पी> यहां, मैं स्केलेटन ऐप का उपयोग करके प्रदर्शन में सुधार के बारे में बात करूंगा। यह निम्नलिखित टूलींग का उपयोग करता है: upstash_redis :रेडिस के लिए अपस्टैश के साथ काम करने के लिए एक डेनो मॉड्यूल - डेनो फ्रेश:डेनो में सर्वर-साइड रेंडर (एसएसआर) ऐप्स बनाने के लिए एक नया, उत्पादन-तैयार फ्रेमवर्क
- सर्वर रहित लॉगिंग:हम यहां कंसोल का उपयोग करते हैं, लेकिन आपके तैनात ऐप के लिए, लाइव माप तक पहुंचने के लिए आपको लॉगटेल जैसी सेवा की आवश्यकता होगी
सेटअप
<पी> नोड और डेनो के बीच एक महत्वपूर्ण अंतर यह है कि आप अपने कोड में तीसरे पक्ष के मॉड्यूल तक कैसे पहुंचते हैं। डेनो package.json के बजाय यूआरएल और आयात मानचित्रों के साथ काम करता है फ़ाइल. upstash_redis के लिए पूरा यूआरएल उदाहरण के लिए, https://deno.land/x/upstash_redis@v1.20.0 है . आरंभ करने के लिए एक नया Deno Fresh ऐप बनाएं। deno run -A -r https://fresh.deno.dev upstash-redis-deno-perf
<पी> यदि आप इसे पहली बार आज़मा रहे हैं, तो आप कुछ टर्मिनल कमांड के साथ अपने सिस्टम पर डेनो को स्वयं सेट कर सकते हैं। <पी> अब आप अपस्टैश को import_map.json में जोड़ सकते हैं प्रोजेक्ट रूट निर्देशिका में: {
"imports": {
"@/": "./",
"$fresh/": "https://deno.land/x/fresh@1.1.2/",
// ...TRUNCATED
"$std/": "https://deno.land/std@0.177.0/",
"upstash/": "https://deno.land/x/upstash_redis@v1.20.0/"
}
}
@/ सुविधा के लिए एक आयात उपनाम परिभाषित करता है। इससे आप components आयात कर सकते हैं (प्रोजेक्ट रूट डायरेक्टरी में) @/components का उपयोग करके इससे कोई फर्क नहीं पड़ता कि आपकी स्रोत फ़ाइल किस फ़ोल्डर में है।
$std/ डेनो स्टैंडर्ड लाइब्रेरी के लिए हमारा उपनाम है जिसमें .env पढ़ने के लिए एक उपयोगिता फ़ंक्शन है पर्यावरण परिवर्तनीय फ़ाइलें.
upstash/ हमें प्रोजेक्ट में किसी भी टाइपस्क्रिप्ट या जावास्क्रिप्ट स्रोत फ़ाइल से रेडिस लाइब्रेरी के लिए अपस्टैश तक पहुंचने की सुविधा देता है।
रेडिस और परफॉर्मेंस एपीआई के लिए अपस्टैश:स्केलेटन ऐप
<पी> स्केलेटन ऐप इसमें खींच लेगा: - टिनीबर्ड (सर्वर रहित क्लिकहाउस) से वेब एनालिटिक्स का उपयोग करके पिछले 28 दिनों में पृष्ठ दृश्य
- वेबमेंटेशन का उपयोग करके पेज लाइक किया जाता है
<पी> ये डेटा फ़ेच अनुरोधों का उपयोग करके प्राप्त किया जाता है, जो हमारे सर्वर कार्यों को वास्तविक दुनिया के व्यावसायिक ऐप का काफी हद तक प्रतिनिधि बनाता है। likes और views वेरिएबल इन दो एपीआई से प्रतिक्रियाएँ रखते हैं जिन्हें हम फ्रंटएंड में प्रदर्शित करते हैं। <पी>
<पी> सर्वर handler उस पेज का कोड कुछ इस तरह दिखता है: export const handler: Handlers<Data> = {
async GET(request, context) {
const { url } = request;
const { pathname } = new URL(url);
const likes = await getWebmentionLikes(pathname);
const views = await getTinybirdViews({ days: 28 });
return context.render({ likes, views });
},
};
<पी> हम pathname निकालते हैं आने वाले request से ऑब्जेक्ट, फिर pathname का उपयोग करें डेटा सहायक कार्यों में और अंत में, दूरस्थ रूप से प्राप्त मान लौटाएँ। <पी> दक्षता के लिए, सहायक कार्यों के लिए कॉल को पुनर्गठित किया जा सकता है: const [likes, views] = await Promise.all([
getWebmentionLikes(pathname),
getTinybirdViews({ days: 28 }),
]);
जावास्क्रिप्ट प्रदर्शन वेब एपीआई
<पी> निष्पादन माप आमतौर पर अनुकूलन में पहला कदम होना चाहिए। दर सीमित करने का कदम हमेशा वैसा नहीं होता जैसा आप उम्मीद करते हैं। मापने के बिना, आप आसानी से एक उप-इष्टतम समाधान पर समय और संसाधन खर्च कर सकते हैं। प्रदर्शन एपीआई यहीं मदद नहीं कर सकती। इस अनुभाग में हम देखते हैं कि हम इसका उपयोग यह निर्धारित करने के लिए कैसे कर सकते हैं कि ऐप में रेडिस के लिए अपस्टैश का उपयोग करना सबसे अधिक सार्थक कहां है। <पी> window.performance आपको क्लाइंट ब्राउज़र से परफॉर्मेंस वेब एपीआई तक पहुंच प्रदान करता है। डेनो सर्वर पर वेब एपीआई का उपयोग करने का समर्थन करता है और इसलिए performance आपके डेनो सर्वर-साइड कोड में विश्व स्तर पर उपलब्ध है। यहां दो प्रदर्शन विधियां हैं जिनका आप उपयोग करना चाहेंगे: performance.mark('your-mark-name') :एक PerformanceMark बनाता है वस्तु, जो समय में एक बिंदु का प्रतिनिधित्व करती है। जब आप चिह्न के साथ कोई माप बनाते हैं तो नाम पैरामीटर का उपयोग किया जाता है।
performance.measure('your description', startMarkName, finishMarkName) :एक PerformanceMeasure बनाता है वस्तु. यह प्रारंभ और समाप्ति समय चिह्नों को एक लेबल के साथ जोड़ता है, जो लॉगिंग और गणना करने के लिए उपयोगी है कि ईवेंट चलने में कितना समय लगा।
timeEvent :प्रदर्शन सहायक फ़ंक्शन
<पी> अब जब हम बुनियादी बातें जान गए हैं, तो आइए एक timeEvent बनाएं समारोह. यह PerformanceMeasure की एक सरणी लेगा ऑब्जेक्ट और एक फ़ंक्शन जिसे हम इनपुट के रूप में टाइम करना चाहते हैं। timeEvent एक प्रारंभ चिह्न बनाएगा, पारित किए गए फ़ंक्शन को लागू करेगा, फिर तुरंत एक समापन चिह्न बनाएगा। अंत में, यह PerformanceMeasure की सरणी को बदल देगा इसे इनपुट के रूप में प्राप्त ऑब्जेक्ट, नया जोड़ना। यहां utils/performance.ts से कोड दिया गया है : export async function timeEvent<EventReturnType>(
eventFunction: () => Promise<EventReturnType>,
{
description,
performanceMeasures,
}: { description: string; performanceMeasures: PerformanceMeasure[] },
): Promise<EventReturnType> {
// prepare
const startName = `${description}-started`;
const finishName = `${description}-finished`;
// time
performance.mark(startName);
const result = await eventFunction();
performance.mark(finishName);
// record
performanceMeasures.push(
performance.measure(description, startName, finishName),
);
return result;
}
<पी> फ़ंक्शन सामान्य है, हालांकि स्केलेटन ऐप के लिए, EventReturnType हमेशा एक संख्या होगी. माप के साथ सर्वर कोड अपडेट करना
<पी> हम नए timeEvent का उपयोग कर सकते हैं हैंडलर में फ़ंक्शन करें, फिर तुलना चलाना प्रारंभ करें। यहां अद्यतन सर्वर हैंडलर कोड है: import type { Handlers, PageProps } from "$fresh/server.ts";
import "$std/dotenv/load.ts"; /* included for visibility here, typically you
can import once for project in `dev.ts` */
import { timeEvent } from "@/utils/performance.ts";
// ...TRUNCATED
export const handler: Handlers<Data> = {
async GET(request, context) {
// ...TRUNCATED
const performanceMeasures: PerformanceMeasure[] = [];
const [likes, views] = await Promise.all([
timeEvent<number>(() => getWebmentionLikes(pathname), {
description: "web-mention-likes",
performanceMeasures,
}),
timeEvent<number>(() => getTinybirdViews({ days: 28 }), {
description: "analytics-views",
performanceMeasures,
}),
]);
// Replace with a serverless logging service for production
console.log({ performanceMeasures });
return context.render({ likes, views });
},
};
<पी> timeEvent फ़ंक्शन उस फ़ंक्शन का परिणाम लौटाता है जिसे हम उसमें पास करते हैं। यह प्रॉपर्टी हमें केवल दो डेटा हेल्पर फ़ंक्शंस को लपेटने की सुविधा देती है जो हमारे पास पहले timeEvent में थे कॉल. हम यहां स्थानीय स्तर पर चल रहे हैं। एक प्रोडक्शन ऐप के लिए, आपको अपनी लाइव साइट पर माप चलाने की ज़रूरत है, क्योंकि आपके सर्वर पर बैकबोन कनेक्शन स्थानीय कनेक्शन से अलग प्रदर्शन करेगा। सर्वर पर चलते समय उपायों को रिकॉर्ड करने के लिए लॉगटेल जैसी लॉगिंग सेवा का उपयोग करें। <पी>
<पी> कंसोल लॉग के कैप्चर में, आप PerformanceMeasure देख सकते हैं ऑब्जेक्ट निम्नलिखित माप मान प्रदान करता है (जिसका हमने पहले उल्लेख किया था): - नाम
- प्रारंभ समय
- अवधि (मिलीसेकंड में)
<पी> आदर्श रूप से, हमें ऐप को प्रस्तुत करने के लिए डेटा मान (पसंद और दृश्य) दोनों की आवश्यकता है। यहां उन्होंने एक-दूसरे के बराबर ही समय (2 सेकंड) लिया। यदि एक फ़ंक्शन दूसरे की तुलना में बहुत धीमी गति से चलता है, तो हम सबसे धीमी वैल्यू के लिए रेडिस कैशिंग के लिए अपस्टैश जोड़ देंगे। इसके बजाय, यहां हम इसे दोनों में जोड़ देंगे। ध्यान दें, उत्पादन में, हम कम से कम कुछ सौ डेटा पॉइंट चाहेंगे। फिर हम तुलना के लिए माध्य या P90 जैसे समग्र माप का उपयोग कर सकते हैं। एनालिटिक्स हेल्पर कोड में रेडिस के लिए अपस्टैश जोड़ना
<पी> आइए एनालिटिक्स हेल्पर फ़ंक्शन में रेडिस के लिए अपस्टैश जोड़ने के लिए कोड देखें। Webmentions हेल्पर फ़ंक्शन समान है और आप इसे GitHub रेपो (नीचे लिंक) में पूर्ण रूप से देख सकते हैं। import { Redis } from "upstash/mod.ts";
const UPSTASH_REDIS_REST_TOKEN = Deno.env.get("UPSTASH_REDIS_REST_TOKEN");
if (typeof UPSTASH_REDIS_REST_TOKEN === "undefined") {
console.error("env `UPSTASH_REDIS_REST_TOKEN` must be set");
}
const UPSTASH_REDIS_REST_URL = Deno.env.get("UPSTASH_REDIS_REST_URL");
if (typeof UPSTASH_REDIS_REST_URL === "undefined") {
console.error("env `UPSTASH_REDIS_REST_URL` must be set");
}
const redis = new Redis({
token: UPSTASH_REDIS_REST_TOKEN,
url: UPSTASH_REDIS_REST_URL,
});
<पी> सबसे पहले, हमें रेडिस ऑब्जेक्ट के लिए एक अपस्टैश प्रारंभ करना होगा। आपको UPSTASH_REDIS_REST_TOKEN की आवश्यकता है और UPSTASH_REDIS_REST_URL अपस्टैश कंसोल से मान। यदि आपके पास अभी तक एक अपस्टैश खाता नहीं है तो इसे स्थापित करना त्वरित है। दोनों मान जोड़ें (UPSTASH_REDIS_REST_TOKEN और UPSTASH_REDIS_REST_URL ) से .env तक प्रोजेक्ट रूट निर्देशिका में फ़ाइल. <पी> ऊपर पहली पंक्ति में ध्यान दें, हम upstash का उपयोग करते हैं आयात मानचित्र से कुंजी जिसे हमने पहले सेट किया था। यह प्रत्येक टाइपस्क्रिप्ट फ़ाइल में पूर्ण आयात URL जोड़ने से अधिक सुविधाजनक है। upstash_redis की अगली रिलीज़ कब होगी उपलब्ध हो जाने पर आपको केवल संस्करण संख्या को एक ही स्थान पर अपडेट करना होगा। <पी> यहां getTinybirdViews है फ़ंक्शन: export async function getTinybirdViews({
days,
}: {
days: number;
}): Promise<number> {
try {
// ...TRUNCATED
const cachedCount = (await redis.get("view-count")) as number | null;
if (cachedCount != null) {
return cachedCount;
}
// ...TRUNCATED
const response = await fetch(
`https://api.tinybird.co/v0/pipes/${TINYBIRD_PIPE_NAME}.json?${params.toString()}`,
{
headers: {
Authorization: `Bearer ${TINYBIRD_TOKEN}`,
},
},
);
const {
data: [{ count_sessions: count = -1 }],
} = await response.json();
if (typeof count === "number" && count > 0) {
const CACHE_TTL_SECONDS = 14_400;
await redis.set("view-count", count);
await redis.expire("view-count", CACHE_TTL_SECONDS);
}
return count;
} catch (error: unknown) {
// ...TRUNCATED
}
}
<पी> यहाँ हम: - जांचें कि क्या
view-count के लिए रेडिस कैश्ड मान के लिए पहले से ही कोई अपस्टैश मौजूद है redis.get('view-count') पर कॉल के साथ .
- यदि कोई कैश्ड मान है तो उसे वापस कर दें, अन्यथा टिनीबर्ड से नया मान प्राप्त करें।
-
redis.set('view-count', value) पर कॉल करके रेडिस कैश के लिए अपस्टैश में नए मूल्य को स्टोर करें और समाप्ति तिथि सेट करें। फिर redis.expire(TTL) . यह जीने केसमयके साथ मूल्य निर्धारित करता है (टीटीएल ) वह मान जिसके बाद डेटा को पुराना माना जाता है। हमने TTL सेट किया यहाँ चार घंटे तक. getTinybirdViews पर कॉल के लिए उस अवधि के बाद, हम नए मूल्य के लिए टाइनीबर्ड पर प्रहार करेंगे।
<पी>
<पी> दोनों डेटा क्वेरीज़ में एकीकृत रेडिस के लिए अपस्टैश के साथ पेज को (कुछ बार) रीफ्रेश करने पर हम देखते हैं कि चीज़ें तेज़ हो गई हैं। यहां हम केवल 2 सेकंड से घटकर लगभग 0.29 सेकंड रह गए। यहां संख्याओं के बारे में बहुत अधिक न पढ़ें क्योंकि हम स्थानीय स्तर पर चल रहे हैं और हमारे पास कई डेटा पॉइंट भी नहीं हैं। यह देखने के लिए कि आप किस प्रकार के लाभ प्राप्त कर सकते हैं, अपने स्वयं के ऐप्स पर सेवा आज़माएँ। रेडिस और परफॉर्मेंस एपीआई के लिए अपस्टैश:रैपिंग अप
<पी> यहां, हमने देखा कि आप अपने अनुकूलन प्रयासों को कहां केंद्रित करना है, इस पर निर्णय लेने में सहायता के लिए जावास्क्रिप्ट प्रदर्शन एपीआई का उपयोग कैसे कर सकते हैं। इसके अलावा हमने देखा कि आप डेनो फ्रेश में रेडिस के लिए अपस्टैश कैसे लागू कर सकते हैं। अंत में हमें पता चला कि डेनो सीखने की अवस्था को समतल करते हुए वेब एपीआई सर्वर साइड का समर्थन करता है। अनुकूलन के लिए डेनो का दूसरा बड़ा लाभ त्वरित तैनाती है, जो आपको एक छोटा फीडबैक लूप देता है और प्रदर्शन को ठीक करते समय आपको तेजी से आगे बढ़ने की सुविधा देता है। <पी> मुझे आशा है कि आपको रेडिस के लिए अपस्टैश और परफॉर्मेंस एपीआई के बारे में पढ़ना उपयोगी लगा होगा। यदि आप डेनो या डेनो फ्रेश में नए हैं, तो डेनो के साथ शुरुआत करने पर मेरे द्वारा बनाई गई कुछ सामग्री पर एक नज़र डालें। आप GitHub पर ऐप का पूरा कोड खोल सकते हैं।