নেটওয়ার্কিং অপ্টিমাইজ করা

Cloud Functions সরলতা আপনাকে দ্রুত কোড তৈরি করতে এবং সার্ভারবিহীন পরিবেশে এটি চালাতে সাহায্য করে। মাঝারি স্কেলে, ফাংশন চালানোর খরচ কম, এবং আপনার কোড অপ্টিমাইজ করা উচ্চ অগ্রাধিকার বলে মনে নাও হতে পারে। তবে, আপনার স্থাপনা যত বড় হচ্ছে, আপনার কোড অপ্টিমাইজ করা তত গুরুত্বপূর্ণ হয়ে উঠছে।

এই ডকুমেন্টে আপনার ফাংশনের জন্য নেটওয়ার্কিং কীভাবে অপ্টিমাইজ করবেন তা বর্ণনা করা হয়েছে। নেটওয়ার্কিং অপ্টিমাইজ করার কিছু সুবিধা নিম্নরূপ:

  • প্রতিটি ফাংশন কলে নতুন আউটবাউন্ড সংযোগ স্থাপনে ব্যয়িত CPU সময় হ্রাস করুন।
  • সংযোগ বা DNS কোটা শেষ হয়ে যাওয়ার সম্ভাবনা হ্রাস করুন।

স্থায়ী সংযোগ বজায় রাখা

এই বিভাগে একটি ফাংশনে স্থায়ী সংযোগ বজায় রাখার উদাহরণ দেওয়া হয়েছে। এটি করতে ব্যর্থ হলে সংযোগ কোটা দ্রুত শেষ হয়ে যেতে পারে।

এই বিভাগে নিম্নলিখিত পরিস্থিতিগুলি কভার করা হয়েছে:

  • HTTP/S সম্পর্কে
  • গুগল এপিআই

HTTP/S অনুরোধ

নিচের অপ্টিমাইজ করা কোড স্নিপেটটি দেখায় যে প্রতিটি ফাংশন ইনভোকেশনের সময় একটি নতুন সংযোগ তৈরি করার পরিবর্তে কীভাবে স্থায়ী সংযোগ বজায় রাখা যায়:

নোড.জেএস

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 বস্তুতে রূপান্তরিত করা যেতে পারে এমন যেকোনো মানের সেট ফেরত দেয়।

গুগল এপিআই অ্যাক্সেস করা হচ্ছে

নিচের উদাহরণটি Cloud Pub/Sub ব্যবহার করে, তবে এই পদ্ধতিটি অন্যান্য ক্লায়েন্ট লাইব্রেরির জন্যও কাজ করে—যেমন, Cloud Natural Language অথবা Cloud Spanner । মনে রাখবেন যে কর্মক্ষমতা উন্নতি নির্দিষ্ট ক্লায়েন্ট লাইব্রেরির বর্তমান বাস্তবায়নের উপর নির্ভর করতে পারে।

একটি Pub/Sub ক্লায়েন্ট অবজেক্ট তৈরি করলে প্রতি ইনভোকেশনে একটি সংযোগ এবং দুটি DNS কোয়েরি তৈরি হয়। অপ্রয়োজনীয় সংযোগ এবং DNS কোয়েরি এড়াতে, নীচের নমুনায় দেখানো পদ্ধতিতে গ্লোবাল স্কোপে Pub/Sub ক্লায়েন্ট অবজেক্ট তৈরি করুন:

নোড.জেএস

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 এনভায়রনমেন্ট ভেরিয়েবলটি পাইথন 3.7 রানটাইমে স্বয়ংক্রিয়ভাবে সেট করা হয়। পরবর্তী রানটাইমে, ফাংশন ডিপ্লয়মেন্টে এটি নির্দিষ্ট করতে ভুলবেন না। কনফিগার এনভায়রনমেন্ট ভেরিয়েবল দেখুন।

বহির্গামী সংযোগ

বহির্গামী অনুরোধের সময়সীমা

আপনার ফাংশন থেকে VPC নেটওয়ার্কে অনুরোধের জন্য ১০ মিনিট নিষ্ক্রিয় সময়ের পরে একটি সময়সীমা থাকে। আপনার ফাংশন থেকে ইন্টারনেটে অনুরোধের জন্য, ২০ মিনিট নিষ্ক্রিয় সময়ের পরে একটি সময়সীমা থাকে।

আউটবাউন্ড সংযোগ রিসেট করা হচ্ছে

আপনার ফাংশন থেকে VPC নেটওয়ার্ক এবং ইন্টারনেট উভয়ের সাথে সংযোগ স্ট্রিমগুলি মাঝে মাঝে বন্ধ করা যেতে পারে এবং অন্তর্নিহিত অবকাঠামো পুনরায় চালু বা আপডেট করা হলে প্রতিস্থাপন করা যেতে পারে। যদি আপনার অ্যাপ্লিকেশন দীর্ঘস্থায়ী সংযোগগুলি পুনরায় ব্যবহার করে, তাহলে আমরা সুপারিশ করি যে আপনি একটি মৃত সংযোগের পুনঃব্যবহার এড়াতে সংযোগগুলি পুনরায় স্থাপন করার জন্য আপনার অ্যাপ্লিকেশনটি কনফিগার করুন।

আপনার ফাংশন লোড-টেস্টিং

আপনার ফাংশনটি গড়ে কতগুলি সংযোগ সম্পাদন করে তা পরিমাপ করার জন্য, এটিকে HTTP ফাংশন হিসাবে স্থাপন করুন এবং নির্দিষ্ট QPS-এ এটি চালু করার জন্য একটি পারফরম্যান্স-টেস্টিং ফ্রেমওয়ার্ক ব্যবহার করুন। একটি সম্ভাব্য পছন্দ হল Artillery , যা আপনি একটি একক লাইন দিয়ে চালু করতে পারেন:

$ artillery quick -d 300 -r 30 URL

এই কমান্ডটি ৩০০ সেকেন্ডের জন্য ৩০ QPS এ প্রদত্ত URL টি আনে।

পরীক্ষাটি সম্পন্ন করার পর, ক্লাউড কনসোলের Cloud Functions API কোটা পৃষ্ঠায় আপনার সংযোগ কোটার ব্যবহার পরীক্ষা করুন। যদি ব্যবহার ধারাবাহিকভাবে প্রায় 30 (অথবা এর একাধিক) হয়, তাহলে আপনি প্রতিটি ইনভোকেশনে একটি (অথবা একাধিক) সংযোগ স্থাপন করছেন। আপনার কোডটি অপ্টিমাইজ করার পরে, আপনি কেবল পরীক্ষার শুরুতে কয়েকটি (10-30) সংযোগ দেখতে পাবেন।

একই পৃষ্ঠায় CPU কোটা প্লটে আপনি অপ্টিমাইজেশনের আগে এবং পরে CPU খরচ তুলনা করতে পারেন।