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

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

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

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

दर्शकों के साथ लगातार जुड़े रहना

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

इस सेक्शन में, इन स्थितियों की जानकारी दी गई है:

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

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

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

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 रनटाइम में अपने-आप सेट हो जाता है. बाद के रनटाइम में, इसे फ़ंक्शन डिप्लॉयमेंट में ज़रूर बताएं. एनवायरमेंट वैरिएबल कॉन्फ़िगर करना लेख पढ़ें.

आपके फ़ंक्शन की लोड टेस्टिंग

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

$ artillery quick -d 300 -r 30 URL

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

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

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