Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Redis

Upstash for Redis के साथ Deno ऐप प्रदर्शन को बढ़ाएं: सर्वरलेस कैशिंग जो रिस्पॉन्स टाइम को कम करती है

Upstash for Redis और Performance API पर इस लेख में, हम देखते हैं कि आप Deno ऐप में Upstash for Redis का सर्वोत्तम उपयोग कैसे कर सकते हैं। Upstash for Redis सर्वर-साइड कैशिंग के लिए आदर्श एक सर्वरलेस डेटाबेस है। मैं जिस वेब ऐप पर काम कर रहा था, वह प्रारंभिक सर्वर प्रतिक्रिया समय पर खराब स्कोर कर रहा था। Lighthouse 500 ms रिपोर्ट कर रहा था। Upstash कैश जोड़कर, मैंने इसे 150 ms से नीचे ला दिया और ऑडिट पास कर लिया। कठिन हिस्सा कैश जोड़ना नहीं था; जैसा कि होता है, यह पता लगाना कि कैश का उपयोग कहां करना है, प्रदर्शन को न्यूनतम कार्य के साथ बढ़ावा देने के लिए महत्वपूर्ण था। केवल प्रदर्शन को मापकर मैं बॉटलनेक की पहचान कर सका और न्यूनतम कार्य के साथ प्रदर्शन को बढ़ावा दे सका। हम इस लेख में प्रदर्शन माप पर करीब से नज़र डालते हैं।

मेरा प्रोजेक्ट एक Deno Fresh वेब ऐप था। Deno में तत्काल बिल्ड और डेप्लॉय होते हैं। यह ऑप्टिमाइज़ेशन के लिए काम करने के लिए एक सपने का माहौल बनाता है। फीडबैक लूप छोटा है। आप स्थानीय रूप से एक ऑप्टिमाइज़ेशन कोड कर सकते हैं, इसे सर्वर पर पुश कर सकते हैं और तुरंत रिमोट साइट का परीक्षण कर सकते हैं।

स्टैक

यहां, मैं एक स्केलेटन ऐप का उपयोग करके प्रदर्शन में सुधार के बारे में बात करूंगा। यह निम्नलिखित टूलिंग का उपयोग करता है:

  • upstash_redis: Upstash for Redis के साथ काम करने के लिए एक Deno मॉड्यूल
  • Deno Fresh: Deno में सर्वर-साइड रेंडर्ड (SSR) ऐप बनाने के लिए एक नया, प्रोडक्शन-रेडी फ्रेमवर्क
  • सर्वरलेस लॉगिंग: हम यहां कंसोल का उपयोग करते हैं, लेकिन आपके डेप्लॉय्ड ऐप के लिए, लाइव माप तक पहुंचने के लिए आपको Logtail जैसी सेवा की आवश्यकता होगी

सेटअप

Node और Deno के बीच एक महत्वपूर्ण अंतर यह है कि आप अपने कोड में थर्ड-पार्टी मॉड्यूल कैसे एक्सेस करते हैं। Deno package.json फाइल के बजाय URL और इम्पोर्ट मैप के साथ काम करता है। upstash_redis के लिए पूर्ण URL, उदाहरण के लिए, https://deno.land/x/upstash_redis@v1.20.0 है। शुरू करने के लिए एक नया Deno Fresh ऐप बनाएं।

deno run -A -r https://fresh.deno.dev upstash-redis-deno-perf

यदि आप पहली बार इसे आज़मा रहे हैं तो आप कुछ टर्मिनल कमांड के साथ अपने सिस्टम पर Deno सेटअप कर सकते हैं।

अब आप प्रोजेक्ट रूट डायरेक्टरी में import_map.json में Upstash जोड़ सकते हैं:

{
  "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/ Deno स्टैंडर्ड लाइब्रेरी के लिए हमारा एलियास है जिसमें .env एनवायरनमेंट वेरिएबल फाइल पढ़ने के लिए एक यूटिलिटी फंक्शन है।
  • upstash/ हमें प्रोजेक्ट में किसी भी TypeScript या JavaScript सोर्स फाइल से Upstash for Redis लाइब्रेरी तक पहुंचने देता है।

Upstash for Redis और Performance API: स्केलेटन ऐप

स्केलेटन ऐप इसमें खींचेगा:

  • Tinybird (सर्वरलेस Clickhouse) से वेब एनालिटिक्स का उपयोग करके पिछले 28 दिनों में पेज व्यू
  • Webmentions का उपयोग करके पेज लाइक

ये डेटा fetch अनुरोधों का उपयोग करके प्राप्त किए जाते हैं, जिससे हमारे सर्वर टास्क वास्तविक दुनिया के बिजनेस ऐप के काफी प्रतिनिधि होते हैं। likes और views वेरिएबल इन दो API से प्रतिक्रियाओं को धारण करते हैं जिन्हें हम फ्रंटएंड में प्रदर्शित करते हैं।

Upstash for Redis के साथ Deno ऐप प्रदर्शन को बढ़ाएं: सर्वरलेस कैशिंग जो रिस्पॉन्स टाइम को कम करती है

उस पेज के लिए सर्वर 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 });
  },
};

हम इनकमिंग request ऑब्जेक्ट से pathname निकालते हैं, फिर डेटा हेल्पर फंक्शन में pathname का उपयोग करते हैं, और अंत में, रिमोटली सोर्स्ड मान वापस करते हैं।

दक्षता के लिए, हेल्पर फंक्शन के कॉल को पुनर्गठित किया जा सकता है:

const [likes, views] = await Promise.all([
  getWebmentionLikes(pathname),
  getTinybirdViews({ days: 28 }),
]);

JavaScript Performance Web API

प्रदर्शन माप आमतौर पर ऑप्टिमाइज़ेशन में पहला कदम होना चाहिए। रेट लिमिटिंग चरण हमेशा वह नहीं होता जिसकी आप अपेक्षा करते हैं। माप के बिना, आप आसानी से समय और संसाधनों को खर्च कर सकते हैं जो एक उप-इष्टतम समाधान बन जाता है। Performance API यहां बहुत मदद कर सकती है। इस खंड में हम देखते हैं कि हम इसका उपयोग यह निर्धारित करने के लिए कैसे कर सकते हैं कि ऐप में Upstash for Redis का उपयोग करना सबसे अधिक समझदारी कहां है।

window.performance आपको क्लाइंट ब्राउज़र से Performance Web API तक पहुंच प्रदान करता है। Deno सर्वर पर Web APIs के उपयोग का समर्थन करता है और इसलिए performance आपके Deno सर्वर-साइड कोड में विश्व स्तर पर उपलब्ध है। यहां दो प्रदर्शन विधियां हैं जिनका आप उपयोग करना चाहेंगे:

  • 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> {
  // तैयार करें
  const startName = `${description}-started`;
  const finishName = `${description}-finished`;
  // समय
  performance.mark(startName);
  const result = await eventFunction();
  performance.mark(finishName);
  // रिकॉर्ड
  performanceMeasures.push(
    performance.measure(description, startName, finishName),
  );
  return result;
}

फंक्शन जेनेरिक है, हालांकि स्केलेटन ऐप के लिए, EventReturnType हमेशा एक नंबर होगा।

माप के साथ सर्वर कोड अपडेट करना

हम नए timeEvent फंक्शन का उपयोग हैंडलर में कर सकते हैं, फिर तुलना चलाना शुरू कर सकते हैं। यहां अपडेटेड सर्वर हैंडलर कोड है:

import type { Handlers, PageProps } from "$fresh/server.ts";
import "$std/dotenv/load.ts";
/* यहां दृश्यता के लिए शामिल, आमतौर पर आप प्रोजेक्ट में एक बार `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,
      }),
    ]);
    // प्रोडक्शन के लिए सर्वरलेस लॉगिंग सर्विस से बदलें
    console.log({ performanceMeasures });
    return context.render({ likes, views });
  },
};

timeEvent फंक्शन उस फंक्शन का परिणाम लौटाता है जिसे हम इसमें पास करते हैं। यह गुण हमें बस उन दो डेटा हेल्पर फंक्शन को लपेटने देता है जो हमारे पास पहले timeEvent कॉल में थे। हम यहां स्थानीय रूप से चला रहे हैं। एक प्रोडक्शन ऐप के लिए, आपको अपनी लाइव साइट पर माप चलाने की आवश्यकता है, क्योंकि आपके सर्वर पर बैकबोन कनेक्शन स्थानीय वालों से अलग प्रदर्शन करेंगे। सर्वर पर चलाते समय, माप रिकॉर्ड करने के लिए Logtail जैसी लॉगिंग सेवा का उपयोग करें।

Upstash for Redis के साथ Deno ऐप प्रदर्शन को बढ़ाएं: सर्वरलेस कैशिंग जो रिस्पॉन्स टाइम को कम करती है

कंसोल लॉग के कैप्चर में, आप देख सकते हैं कि PerformanceMeasure ऑब्जेक्ट निम्न माप मान प्रदान करता है (जिन्हें हमने पहले उल्लेख किया था):

  • नाम
  • प्रारंभ समय
  • अवधि (मिलीसेकंड में)

आदर्श रूप से, हमें ऐप को रेंडर करने के लिए दोनों डेटा मान (लाइक्स और व्यूज) की आवश्यकता होती है। यहां उन्होंने लगभग एक ही समय लिया (2 सेकंड)। यदि एक फंक्शन दूसरे की तुलना में बहुत धीमा चला होता, तो हम सबसे धीमे मान के लिए Upstash for Redis कैशिंग जोड़ते। इसके बजाय, यहां हम इसे दोनों में जोड़ेंगे। ध्यान दें, प्रोडक्शन में, हम कम से कम कुछ सौ डेटा पॉइंट चाहेंगे। फिर हम तुलना के लिए माध्य या P90 जैसे समग्र माप का उपयोग कर सकते हैं।

एनालिटिक्स हेल्पर कोड में Upstash for Redis जोड़ना

आइए एनालिटिक्स हेल्पर फंक्शन में Upstash for Redis जोड़ने के लिए कोड देखें। 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 for Redis ऑब्जेक्ट इनिशियलाइज़ करना होगा। आपको Upstash कंसोल से UPSTASH_REDIS_REST_TOKEN और UPSTASH_REDIS_REST_URL मान चाहिए। यदि आपके पास अभी तक कोई नहीं है तो Upstash अकाउंट सेटअप करना त्वरित है। दोनों मानों (UPSTASH_REDIS_REST_TOKEN और UPSTASH_REDIS_REST_URL) को प्रोजेक्ट रूट डायरेक्टरी में .env फाइल में जोड़ें।

ऊपर पहली पंक्ति में ध्यान दें, हम इम्पोर्ट मैप से upstash कुंजी का उपयोग करते हैं जिसे हमने पहले सेटअप किया था। यह प्रत्येक TypeScript फाइल में पूर्ण इम्पोर्ट 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
  }
}

यहां हम:

  1. redis.get('view-count') कॉल करके जांचते हैं कि क्या view-count के लिए पहले से ही Upstash for Redis कैश्ड मान है।
  2. यदि है तो कैश्ड मान वापस करते हैं, अन्यथा Tinybird से एक नया मान प्राप्त करते हैं।
  3. redis.set('view-count', value) कॉल करके फिर redis.expire(TTL) कॉल करके नए मान को Upstash for Redis कैश में स्टोर करते हैं और एक्सपायरी सेट करते हैं। यह मान को एक टाइम टू लिव (TTL) मान के साथ सेट करता है जिसके बाद डेटा को स्टेल माना जाता है। हम यहां TTL को चार घंटे पर सेट करते हैं। उस अवधि के बाद getTinybirdViews के कॉल के लिए, हम एक नए मान के लिए Tinybird को हिट करेंगे।

Upstash for Redis के साथ Deno ऐप प्रदर्शन को बढ़ाएं: सर्वरलेस कैशिंग जो रिस्पॉन्स टाइम को कम करती है

Upstash for Redis को दोनों डेटा क्वेरी में इंटीग्रेटेड करके पेज को रिफ्रेश करने (कुछ बार) पर हम चीजों को तेज होते देखते हैं। यहां हम 2 सेकंड से अधिक से लगभग 0.29 सेकंड पर आ गए। यहां संख्याओं में बहुत अधिक न पढ़ें क्योंकि हम स्थानीय रूप से चल रहे हैं और हमारे पास कई डेटा पॉइंट नहीं हैं। अपनी खुद की ऐप्स पर सेवा को आज़माएं यह देखने के लिए कि आप किस तरह के लाभ प्राप्त कर सकते हैं।

Upstash for Redis और Performance API: समापन

यहां, हमने देखा कि आप JavaScript Performance API का उपयोग कैसे कर सकते हैं ताकि आपके ऑप्टिमाइज़ेशन प्रयासों पर ध्यान केंद्रित करने के निर्णयों को मार्गदर्शन करने में मदद मिल सके। इसके अलावा हमने देखा कि आप Deno Fresh में Upstash for Redis को कैसे लागू कर सकते हैं। अंत में हमने पाया कि Deno सर्वर-साइड Web APIs का समर्थन करता है, जिससे लर्निंग कर्व समतल होता है। ऑप्टिमाइज़ेशन के लिए Deno का अन्य बड़ा लाभ तत्काल डेप्लॉय है, जो आपको एक छोटा फीडबैक लूप देता है और प्रदर्शन को फाइन-ट्यून करते समय आपको तेजी से आगे बढ़ने देता है।

मुझे आशा है कि आपको Upstash for Redis और Performance API के बारे में पढ़ना मूल्यवान लगा। यदि आप Deno या Deno Fresh में नए हैं, तो Deno के साथ शुरुआत करने पर मेरे द्वारा बनाई गई कुछ सामग्री पर एक नज़र डालें। आप GitHub पर ऐप के लिए पूरा कोड खोल सकते हैं।

  1. Java में HTML का उपयोग करके मल्टीलाइन टेक्स्ट रखने के लिए JLabel कैसे बनाएं? Java में HTML का उपयोग करके मल्टीलाइन टेक्स्ट रखने के लिए JLabel कैसे बनाएं?

    मल्टीलाइन टेक्स्ट रखने के लिए, JLabel के तहत HTML सेट करें: JLabel = new JLabel(<html><strong> + Line1<br>Line2</strong></html>,JLabel.LEFT); उपरोक्त JLabel में मल्टीलाइन टेक्स्ट बनाएगा: Line1 Line2 निम्नलिखित मल्टीलाइन टेक्स्ट रखने के लिए JLabel बनाने का एक उदाहरण है:

  1. Tkinter में Entry विजेट का फॉन्ट साइज कैसे सेट करें? Tkinter में Entry विजेट का फॉन्ट साइज कैसे सेट करें?

    Tkinter में Entry विजेट एक बेसिक वन-लाइन कैरेक्टर एंट्री बॉक्स है जो सिंगल लाइन यूजर इनपुट स्वीकार करता है। Entry विजेट की प्रॉपर्टीज जैसे फॉन्ट-साइज और चौड़ाई कॉन्फ़िगर करने के लिए, हम इंलाइन विजेट कंस्ट्रक्टर परिभाषित कर सकते हैं।उदाहरणयहां एक उदाहरण है कि आप Entry विजेट का फॉन्ट-साइज कैसे परिभाषि

  1. HTML फॉर्म में सबमिट बटन का उपयोग कैसे करें? HTML फॉर्म में सबमिट बटन का उपयोग कैसे करें?

    सबमिट बटन क्लिक पर फॉर्म को स्वचालित रूप से सबमिट करता है। HTML फॉर्म का उपयोग करके, आप आसानी से उपयोगकर्ता इनपुट ले सकते हैं। <form> टैग का उपयोग फॉर्म एलिमेंट्स जोड़कर उपयोगकर्ता इनपुट प्राप्त करने के लिए किया जाता है। विभिन्न प्रकार के फॉर्म एलिमेंट्स में टेक्स्ट इनपुट, रेडियो बटन इनपुट, स