नेटवर्किंग का अनुकूलन

क्लाउड फ़ंक्शंस की सरलता आपको तुरंत कोड विकसित करने और उसे सर्वर रहित वातावरण में चलाने की सुविधा देती है। मध्यम पैमाने पर, फ़ंक्शन चलाने की लागत कम है, और आपके कोड को अनुकूलित करना उच्च प्राथमिकता की तरह प्रतीत नहीं हो सकता है। हालाँकि, जैसे-जैसे आपकी तैनाती बढ़ती है, आपके कोड को अनुकूलित करना अधिक महत्वपूर्ण हो जाता है।

यह दस्तावेज़ बताता है कि अपने कार्यों के लिए नेटवर्किंग को कैसे अनुकूलित करें। नेटवर्किंग को अनुकूलित करने के कुछ लाभ इस प्रकार हैं:

  • प्रत्येक फ़ंक्शन कॉल पर नए कनेक्शन स्थापित करने में लगने वाले CPU समय को कम करें।
  • कनेक्शन या DNS कोटा ख़त्म होने की संभावना कम करें।

लगातार कनेक्शन बनाए रखना

यह अनुभाग किसी फ़ंक्शन में लगातार कनेक्शन बनाए रखने के उदाहरण देता है। ऐसा करने में विफलता के परिणामस्वरूप कनेक्शन कोटा जल्दी समाप्त हो सकता है।

इस अनुभाग में निम्नलिखित परिदृश्य शामिल हैं:

  • HTTP/एस
  • गूगल एपीआई

HTTP/एस अनुरोध

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

नोड.जे.एस

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();
});

अजगर

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!")
    

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

Google API तक पहुँचना

नीचे दिया गया उदाहरण क्लाउड पब/सब का उपयोग करता है, लेकिन यह दृष्टिकोण अन्य क्लाइंट लाइब्रेरीज़ के लिए भी काम करता है - उदाहरण के लिए, क्लाउड नेचुरल लैंग्वेज या क्लाउड स्पैनर । ध्यान दें कि प्रदर्शन में सुधार विशेष क्लाइंट लाइब्रेरी के वर्तमान कार्यान्वयन पर निर्भर हो सकता है।

एक पब/सब क्लाइंट ऑब्जेक्ट बनाने से प्रति आमंत्रण एक कनेक्शन और दो DNS क्वेरीज़ उत्पन्न होती हैं। अनावश्यक कनेक्शन और DNS क्वेरीज़ से बचने के लिए, वैश्विक दायरे में पब/सब क्लाइंट ऑब्जेक्ट बनाएं जैसा कि नीचे दिए गए नमूने में दिखाया गया है:

नोड.जे.एस

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');
        }
    });
});

अजगर

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")
    

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

GCP_PROJECT पर्यावरण चर स्वचालित रूप से Python 3.7 रनटाइम में सेट हो जाता है। बाद के रनटाइम में, इसे फ़ंक्शन परिनियोजन पर निर्दिष्ट करना सुनिश्चित करें। पर्यावरण चर कॉन्फ़िगर करें देखें।

अपने फ़ंक्शन का लोड-परीक्षण करें

यह मापने के लिए कि आपका फ़ंक्शन औसतन कितने कनेक्शन निष्पादित करता है, बस इसे एक HTTP फ़ंक्शन के रूप में तैनात करें और इसे कुछ QPS पर लागू करने के लिए एक प्रदर्शन-परीक्षण ढांचे का उपयोग करें। एक संभावित विकल्प आर्टिलरी है, जिसे आप एक पंक्ति से लागू कर सकते हैं:

$ artillery quick -d 300 -r 30 URL

यह कमांड दिए गए URL को 300 सेकंड के लिए 30 QPS पर लाता है।

परीक्षण करने के बाद, क्लाउड कंसोल में क्लाउड फ़ंक्शंस एपीआई कोटा पृष्ठ पर अपने कनेक्शन कोटा के उपयोग की जांच करें। यदि उपयोग लगातार 30 (या इसके एकाधिक) के आसपास है, तो आप प्रत्येक आमंत्रण में एक (या कई) कनेक्शन स्थापित कर रहे हैं। अपने कोड को अनुकूलित करने के बाद, आपको परीक्षण की शुरुआत में ही कुछ (10-30) कनेक्शन दिखाई देने चाहिए।

आप उसी पृष्ठ पर सीपीयू कोटा प्लॉट पर अनुकूलन से पहले और बाद में सीपीयू लागत की तुलना भी कर सकते हैं।