नेटवर्किंग को ऑप्टिमाइज़ किया जा रहा है

Cloud Functions को इस्तेमाल करना आसान है. इसकी मदद से, कोड को तेज़ी से डेवलप किया जा सकता है और उसे सर्वरलेस एनवायरमेंट में चलाया जा सकता है. सामान्य स्केल पर, फ़ंक्शन चलाने की लागत कम होती है. साथ ही, ऐसा लग सकता है कि कोड को ऑप्टिमाइज़ करना ज़्यादा ज़रूरी नहीं है. हालांकि, जैसे-जैसे आपका डिप्लॉयमेंट बढ़ता है, कोड को ऑप्टिमाइज़ करना और भी ज़रूरी हो जाता है.

इस दस्तावेज़ में, फ़ंक्शन के लिए नेटवर्किंग को ऑप्टिमाइज़ करने का तरीका बताया गया है. नेटवर्किंग को ऑप्टिमाइज़ करने के कुछ फ़ायदे यहां दिए गए हैं:

  • हर फ़ंक्शन कॉल पर नए आउटबाउंड कनेक्शन बनाने में लगने वाले सीपीयू समय को कम करें.
  • कनेक्शन या डीएनएस कोटा खत्म होने की संभावना कम हो जाती है.

पर्सिस्टेंट कनेक्शन बनाए रखना

इस सेक्शन में, किसी फ़ंक्शन में परसिस्टेंट कनेक्शन बनाए रखने के उदाहरण दिए गए हैं. ऐसा न करने पर, कनेक्शन कोटा जल्दी खत्म हो सकता है.

इस सेक्शन में इन स्थितियों के बारे में बताया गया है:

  • एचटीटीपी/एस
  • Google API

एचटीटीपी/एस अनुरोध

नीचे दिया गया ऑप्टिमाइज़ किया गया कोड स्निपेट दिखाता है कि हर बार फ़ंक्शन को शुरू करने पर नया कनेक्शन बनाने के बजाय, स्थायी कनेक्शन कैसे बनाए रखें:

Node.js

const http = require('http');
const functions = require('firebase-functions');

// Setting the `keepAlive` option to `true` keeps
// connections open between function invocations
const agent = new http.Agent({keepAlive: true});

exports.function = functions.https.onRequest((request, response) => {
    req = http.request({
        host: '',
        port: 80,
        path: '',
        method: 'GET',
        agent: agent, // Holds the connection open after the first invocation
    }, res => {
        let rawData = '';
        res.setEncoding('utf8');
        res.on('data', chunk => { rawData += chunk; });
        res.on('end', () => {
            response.status(200).send(`Data: ${rawData}`);
        });
    });
    req.on('error', e => {
        response.status(500).send(`Error: ${e.message}`);
    });
    req.end();
});

Python

from firebase_functions import https_fn
import requests

# Create a global HTTP session (which provides connection pooling)
session = requests.Session()

@https_fn.on_request()
def connection_pooling(request):

    # The URL to send the request to
    url = "http://example.com"

    # Process the request
    response = session.get(url)
    response.raise_for_status()
    return https_fn.Response("Success!")
    

यह एचटीटीपी फ़ंक्शन, एचटीटीपी अनुरोध करने के लिए कनेक्शन पूल का इस्तेमाल करता है. यह एक अनुरोध ऑब्जेक्ट (flask.Request) लेता है और जवाब का टेक्स्ट या वैल्यू का कोई भी सेट दिखाता है. इसे make_response का इस्तेमाल करके, Response ऑब्जेक्ट में बदला जा सकता है.

Google API को ऐक्सेस करना

यहां दिए गए उदाहरण में Cloud Pub/Sub का इस्तेमाल किया गया है. हालांकि, यह तरीका अन्य क्लाइंट लाइब्रेरी के लिए भी काम करता है. उदाहरण के लिए, Cloud Natural Language या Cloud Spanner. ध्यान दें कि परफ़ॉर्मेंस में सुधार, कुछ क्लाइंट लाइब्रेरी को लागू करने के मौजूदा तरीके पर निर्भर कर सकता है.

Pub/Sub क्लाइंट ऑब्जेक्ट बनाने पर, हर बार एक कनेक्शन और दो डीएनएस क्वेरी बनती हैं. गैर-ज़रूरी कनेक्शन और डीएनएस क्वेरी से बचने के लिए, ग्लोबल स्कोप में Pub/Sub क्लाइंट ऑब्जेक्ट बनाएं. इसके लिए, यहां दिया गया सैंपल देखें:

node.js

const PubSub = require('@google-cloud/pubsub');
const functions = require('firebase-functions');
const pubsub = PubSub();

exports.function = functions.https.onRequest((req, res) => {
    const topic = pubsub.topic('');

    topic.publish('Test message', err => {
        if (err) {
            res.status(500).send(`Error publishing the message: ${err}`);
        } else {
            res.status(200).send('1 message published');
        }
    });
});

Python

import os

from firebase_functions import https_fn
from google.cloud import pubsub_v1

# from firebase_functions import https_fn
# Create a global Pub/Sub client to avoid unneeded network activity
pubsub = pubsub_v1.PublisherClient()

@https_fn.on_request()
def gcp_api_call(request):

    project = os.getenv("GCP_PROJECT")
    request_json = request.get_json()

    topic_name = request_json["topic"]
    topic_path = pubsub.topic_path(project, topic_name)

    # Process the request
    data = b"Test message"
    pubsub.publish(topic_path, data=data)

    return https_fn.Response("1 message published")
    

यह एचटीटीपी फ़ंक्शन, कैश मेमोरी में सेव की गई क्लाइंट लाइब्रेरी के इंस्टेंस का इस्तेमाल करता है. इससे हर फ़ंक्शन को शुरू करने के लिए ज़रूरी कनेक्शन की संख्या कम हो जाती है. यह अनुरोध ऑब्जेक्ट (flask.Request) लेता है और जवाब का टेक्स्ट या वैल्यू का कोई सेट दिखाता है. इसे make_response का इस्तेमाल करके, Response ऑब्जेक्ट में बदला जा सकता है.

GCP_PROJECT एनवायरमेंट वैरिएबल, Python 3.7 रनटाइम में अपने-आप सेट हो जाता है. बाद के रनटाइम में, फ़ंक्शन डिप्लॉयमेंट के दौरान इसे तय करना न भूलें. एनवायरमेंट वैरिएबल कॉन्फ़िगर करना देखें.

आउटबाउंड कनेक्शन

आउटबाउंड अनुरोधों के लिए टाइम आउट

आपके फ़ंक्शन से वीपीसी नेटवर्क को किए गए अनुरोधों के लिए, 10 मिनट तक कोई गतिविधि न होने पर टाइम आउट हो जाता है. आपके फ़ंक्शन से इंटरनेट पर किए जाने वाले अनुरोधों के लिए, 20 मिनट तक कोई गतिविधि न होने पर टाइम आउट हो जाता है.

आउटबाउंड कनेक्शन रीसेट

आपके फ़ंक्शन से वीपीसी नेटवर्क और इंटरनेट, दोनों के कनेक्शन स्ट्रीम कभी-कभी बंद किए जा सकते हैं. साथ ही, बुनियादी इन्फ़्रास्ट्रक्चर को रीस्टार्ट या अपडेट करने पर, उन्हें बदला जा सकता है. अगर आपका ऐप्लिकेशन लंबे समय तक चलने वाले कनेक्शन का फिर से इस्तेमाल करता है, तो हमारा सुझाव है कि आप अपने ऐप्लिकेशन को कनेक्शन फिर से बनाने के लिए कॉन्फ़िगर करें. इससे, बंद हो चुके कनेक्शन का फिर से इस्तेमाल करने से बचा जा सकता है.

अपने फ़ंक्शन की लोड-टेस्टिंग करना

आपका फ़ंक्शन औसतन कितने कनेक्शन बनाता है, यह मेज़र करने के लिए उसे एचटीटीपी फ़ंक्शन के तौर पर डिप्लॉय करें. साथ ही, किसी खास क्यूपीएस पर उसे शुरू करने के लिए, परफ़ॉर्मेंस की जांच करने वाले फ़्रेमवर्क का इस्तेमाल करें. एक संभावित विकल्प Artillery है, जिसे एक लाइन से शुरू किया जा सकता है:

$ artillery quick -d 300 -r 30 URL

यह कमांड, दिए गए यूआरएल को 300 सेकंड के लिए 30 क्यूपीएस पर फ़ेच करता है.

टेस्ट करने के बाद, Google Cloud कंसोल में Cloud Functions एपीआई कोटा पेज पर जाकर, कनेक्शन कोटे का इस्तेमाल देखें. अगर इस्तेमाल लगातार 30 (या इसके गुणज) के आस-पास है, तो इसका मतलब है कि हर बार शुरू करने पर एक (या कई) कनेक्शन बनाए जा रहे हैं. कोड को ऑप्टिमाइज़ करने के बाद, आपको टेस्ट की शुरुआत में ही कुछ (10 से 30) कनेक्शन दिखेंगे.

इसी पेज पर मौजूद सीपीयू कोटा प्लॉट पर, सीपीयू की लागत की तुलना, ऑप्टिमाइज़ेशन से पहले और बाद में की जा सकती है.